PagerAdapter通过通知更改了适配器的内容 [英] PagerAdapter changed adapters content with notifying

查看:112
本文介绍了PagerAdapter通过通知更改了适配器的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,这是我得到的错误:

So first things first, here's the error that I'm getting:

java.lang.IllegalStateException:应用程序的PagerAdapter 更改适配器的内容而无需调用 PagerAdapter#notifyDataSetChanged!预期的适配器项目数:18, 找到:28

java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 18, found: 28

我在主要活动中使用的是RecyclerView,并且以List<Objects>作为数据集,就可以了.

I'm using a RecyclerView in my main activity and that has a List<Objects> as the dataset, that's all fine.

在该活动中,当我单击RecyclerView项目时,我将其称为第二个活动,该项目基本上是使用ViewPager使用以下代码实现的图库:

From that activity I call the second activity when a RecyclerView item is clicked that is basically a gallery implemented using a ViewPager using this code:

public void startSlideActivity(final int position) {
  DataTransferer.get().storeItems(feed);

  Intent i = new Intent(context, SlideActivity.class);
  ...
  i.putExtra("POSITION", position);
  context.startActivity(i);
}

我的数据太大,无法通过意图传输(使用Parcelable或其他方式),因此我使用单例来保存和传输我的列表,这是代码:

My data is too large to transfer through an intent (using Parcelable or otherwise) so I'm using a singleton to hold and transfer my list, here's the code:

public class DataTransferer {

  private static volatile DataTransferer singleton;

  private List<Thing> items;

  public static DataTransferer get(){
    if (singleton == null) {
      synchronized (DataTransferer.class) {
        singleton = new DataTransferer();
      }
    }
    return singleton;
  }

  private DataTransferer(){
  }

  public void storeItems(List<Thing> items){
    this.items = items;
  }

  public List<Thing> getStoredItems(){
    return items;
  }
}

在第二个活动中,我设置适配器并检索列表,如下所示:

In the second activity I set the adapter and retrieve the list like so:

feed = DataTransferer.get().getStoredItems();
final int position = this.getIntent().getIntExtra("POSITION", 0);
adapter = new FeedPagerAdapter(SlideActivity.this, feed);
viewPager.setAdapter(adapter);
adapter.notifyDataSetChanged();
viewPager.setCurrentItem(position);
viewPager.setOffscreenPageLimit(4);

最后在我的PagerAdapter代码中:

And finally here's in my PagerAdapter code:

public class FeedPagerAdapter extends PagerAdapter {
  @BindView(R.id.item_image_view) ImageView image;

  private final SlideActivity host;
  private List<Thing> items;

  public FeedPagerAdapter(SlideActivity host, List<Thing> items){
    this.host = host;
    this.items = items;
    notifyDataSetChanged();
  }

  @Override
  public Object instantiateItem(ViewGroup parent, int position) {
    View view = LayoutInflater.from(host).inflate(R.layout.item, parent, false);
    ButterKnife.bind(this, view);
    ...
    parent.addView(view);
    return view;
  }

  @Override
  public int getCount() {
    return items.size();
  }

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

  @Override
  public boolean isViewFromObject(View view, Object object) {
    return view == object;
  }
}

我尝试通知onResumeonPause中的数据集以及适配器中的getItemCount,同样的问题.

I've tried notifying the dataset in onResume and onPause and getItemCount in the adapter also, same problem.

回到主要活动,此数据通过网络加载,并在加载完成后将项目添加到列表中.如果我启动我的应用程序并在开始填充RecyclerView时单击该项目,它将打开第二个活动,并且我崩溃了.如果我启动该应用程序并稍等片刻,然后单击RecyclerView项,它将按预期工作.

Back to the main activity, this data is loaded over the network and adds items to the list when the load finishes. If I start my application and click on the item as soon they start to populate the RecyclerView, it opens the second activity and I get the crash. If I start the app and wait a second and click a RecyclerView item, it works as intended.

如果有人对我在启动第二个活动时如何等待以确保列表稳定有任何建议,或者有更好的方法来实现基于网格的RecyclerView图库来打开具有相同数据集的viewpager类型布局,我将不胜感激它.

If anyone has any suggestions on how I can wait to make sure the list is stable when starting the second activity or a better way to implement a grid based RecyclerView gallery to open a viewpager type layout with the same dataset I would really appreciate it.

推荐答案

这是因为您使用的是viewPager.setOffscreenPageLimit(4);行,这意味着viewpager不会在所有4页中都重新创建屏幕.但是,有一个功能可以检测屏幕是否完全可见,称为setUserVisibleHint().您只需要使用如下所示: //对于Fragment情况

It's because you are using this line viewPager.setOffscreenPageLimit(4);, It's mean viewpager won't re-create the screen in all 4 pages. However, there is a function to detect if your screen has been visible completely, it's call setUserVisibleHint(). You just need to use like below: //For the Fragment case

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        if (isVisibleToUser) {
         //TODO notify your recyclerview data over here
        }
    }

对于活动"案例:如果定位到API级别14或更高,则可以使用

For the Activity case: If targeting API level 14 or above, one can use

android.app.Application.ActivityLifecycleCallbacks

public class MyApplication extends Application implements ActivityLifecycleCallbacks {
    private static boolean isInterestingActivityVisible;

    @Override
    public void onCreate() {
        super.onCreate();

        // Register to be notified of activity state changes
        registerActivityLifecycleCallbacks(this);
        ....
    }

    public boolean isInterestingActivityVisible() {
        return isInterestingActivityVisible;
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = true;
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = false;
        }
    }

    // Other state change callback stubs
    ....
}

在AndroidManifest.xml中注册您的应用程序类:

Register your application class in AndroidManifest.xml:

  <application
        android:name="your.app.package.MyApplication"
        android:icon="@drawable/icon"
        android:label="@string/app_name" >

将onPause和onResume添加到项目中的每个Activity:

Add onPause and onResume to every Activity in the project:

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}

在您的finish()方法中,您想使用isActivityVisible()来检查活动是否可见.您还可以在此处检查用户是否选择了一个选项.当两个条件都满足时,继续.

In your finish() method, you want to use isActivityVisible() to check if the activity is visible or not. There you can also check if the user has selected an option or not. Continue when both conditions are met.

这篇关于PagerAdapter通过通知更改了适配器的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆