PagerAdapter 的问题

Posted

技术标签:

【中文标题】PagerAdapter 的问题【英文标题】:Issue with PagerAdapter 【发布时间】:2017-10-11 09:48:37 【问题描述】:

我尝试从 firebase 数据库加载数据库并得到这个异常。这是关于notifyDataSetChanged。我试图在SlideShowAapter 中输入getCount(),但它没有奏效。

例外:

java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! 
Expected adapter item count: 0, found: 1 Pager id: com.example.dave.lomoapp:id/slideShow Pager class: class android.support.v4.view.ViewPager 
Problematic adapter: class com.example.davenguyen.lomoapp.SlideShowAdapter
      at android.support.v4.view.ViewPager.populate(ViewPager.java:1135)
      at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:662)
      at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:624)
      at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:616)
      at com.example.davenguyen.lomoapp.HomeFragment$1.run(HomeFragment.java:71)
      at android.os.Handler.handleCallback(Handler.java:739)
      at android.os.Handler.dispatchMessage(Handler.java:95)
      at android.os.Looper.loop(Looper.java:148)
      at android.app.ActivityThread.main(ActivityThread.java:7331)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

这是我的 SlideShowAdapter

public class SlideShowAdapter extends PagerAdapter 

private boolean doNotifyDataSetChangedOnce = false;
private ArrayList<Genre> genresList;
private LayoutInflater inflater;
private Context context;

public SlideShowAdapter(Context context, ArrayList<Genre> images) 
    this.context = context;
    this.genresList =images;
    inflater = LayoutInflater.from(context);


@Override
public void destroyItem(ViewGroup container, int position, Object object) 
    container.removeView((View) object);


@Override
public int getCount()

    if (doNotifyDataSetChangedOnce) 
        doNotifyDataSetChangedOnce = false;
        notifyDataSetChanged();
    
    return genresList.size();


@Override
public Object instantiateItem(ViewGroup view, int position) 
    View myImageLayout = inflater.inflate(R.layout.slide, view, false);
    ImageView myImage = (ImageView) myImageLayout
            .findViewById(R.id.slideShowImg);
    Picasso.with(context).load(genresList.get(position).getImage()).into(myImage);
    view.addView(myImageLayout, 0);
    view.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

        
    );
    return myImageLayout;


@Override
public boolean isViewFromObject(View view, Object object) 
    return view.equals(object);

这是一个包含我的自定义适配器的片段

public class HomeFragment extends Fragment 

private static ViewPager mPager;
private static int currentPage = 0;

private ArrayList<Genre> genreList = new ArrayList<Genre>();

DatabaseReference mref;

public HomeFragment() 
    // Required empty public constructor



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    // Inflate the layout for this fragment
    View v =inflater.inflate(R.layout.fragment_home, container, false);
    return v;


@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) 
    super.onViewCreated(view, savedInstanceState);


    loadImage();

    mPager = (ViewPager) view.findViewById(R.id.slideShow);
    mPager.setAdapter(new SlideShowAdapter(getActivity(), genreList));
    CircleIndicator indicator = (CircleIndicator) view.findViewById(R.id.indicator);
    indicator.setViewPager(mPager);

    // Auto start of viewpager
    final Handler handler = new Handler();
    final Runnable Update = new Runnable() 
        public void run() 
            if (currentPage == genreList.size()) 
                currentPage = 0;
            
            mPager.setCurrentItem(currentPage++, true);
        
    ;
    Timer swipeTimer = new Timer();
    swipeTimer.schedule(new TimerTask() 
        @Override
        public void run() 
            handler.post(Update);
        
    , 2500, 2500);


private void loadImage() 
    // Get a reference to our genres
    mref = FirebaseDatabase.getInstance().getReference().child("genres");
    // Attach a listener to read the data at our genres reference
    mref.addValueEventListener(new ValueEventListener() 
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) 
            genreList.add (dataSnapshot.getValue(Genre.class));
        

        @Override
        public void onCancelled(DatabaseError databaseError) 
            Log.i("READ_FAIELD","The read failed: " + databaseError.getCode());
        
    );

提前致谢

【问题讨论】:

调用 adapter.notifydatasetchanged();填写数据后 【参考方案1】:

我的猜测是问题在于适配器中的标志doNotifyDataSetChangedOnce。尝试删除 if 并在加载图像后调用 adapter.notifyDataSetChanged()(在 onDataChange 中)。

如果这解决了崩溃但 viewPager 没有更新,您可能需要在适配器中添加以下代码:

    public int getItemPosition(Object object)  
        return POSITION_NONE;
    

【讨论】:

你是救生员。但是,它在将代码分开后可以工作,如@Divyesh Patel 所示 添加public int getItemPosition(Object object) return POSITION_NONE; 后不更新 你在哪里调用 notifyDataSetChanged? @DonDave 如果您在将新项目添加到 arrayList 之后删除它并移动 notifyDataSetChanged 它应该可以工作。【参考方案2】:

这样写:

SlideShowAdapter adapter=new SlideShowAdapter(getActivity(), genreList);
mPager.setAdapter(adapter);
adapter.notifyDataSetChanged();

代替

mPager.setAdapter(new SlideShowAdapter(getActivity(), genreList));

尝试用这个来改变instanceiteItem:

View myImageLayout = inflater.inflate(R.layout.slide, view, false);
    ImageView myImage = (ImageView) myImageLayout
            .findViewById(R.id.slideShowImg);
    Picasso.with(context).load(genresList.get(position).getImage()).into(myImage);

    .
myImageLayout.addView(myImage, 0);
    myImageLayout.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

        
    );
    return myImageLayout;

并删除:

if (doNotifyDataSetChangedOnce) 
        doNotifyDataSetChangedOnce = false;
        notifyDataSetChanged();
    

【讨论】:

这一行得到错误 "cant resolve method addView " myImageLayout.addView(myImage, 0); 从方法中移除 0

以上是关于PagerAdapter 的问题的主要内容,如果未能解决你的问题,请参考以下文章

在使用 PagerAdapter 和 ViewPager 中的选项卡之间滑动时出现问题

日历和 PagerAdapter - 无限次查看

如何从 PagerAdapter 对象获取当前页面字段?

PagerAdapter 中的异步位置

关于ViewPager的适配器之——pagerAdapter加载缓存页面的机制

如何在 PagerAdapter 中返回多个片段(不是 FragmentPagerAdapter)