PagerAdapter通知

时间:2017-04-27 01:40:09

标签: java android android-recyclerview android-viewpager illegalstateexception

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

  

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

我在我的主要活动中使用RecyclerView并且有一个List<Objects>作为数据集,这一切都很好。

在该活动中,当点击RecyclerView项目时,我调用第二个活动,该项目基本上是使用此代码使用ViewPager实现的库:

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或其他方式)所以我使用单例来保存和传输我的列表,这是代码:

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;
  }
}

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

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代码:

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中的数据集,同样的问题。

返回主活动,此数据通过网络加载,并在加载完成后将项目添加到列表中。如果我启动我的应用程序并在他们开始填充RecyclerView时立即点击该项目,它将打开第二个活动并且我得到了崩溃。如果我启动应用程序并等待一秒钟并单击RecyclerView项目,它将按预期工作。

如果有人有任何关于如何确保列表在启动第二个活动时稳定的建议或更好的方法来实现基于网格的RecyclerView库以打开具有相同数据集的viewpager类型布局我会非常感激它。

1 个答案:

答案 0 :(得分:0)

这是因为您正在使用此行viewPager.setOffscreenPageLimit(4);,它的意思是viewpager不会在所有4个页面中重新创建屏幕。但是,有一项功能可以检测您的屏幕是否完全可见,它会调用setUserVisibleHint()。你只需要使用如下: //对于片段案例

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

修改

  

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

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中注册您的应用程序类:

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

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

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

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

finish()方法中,您希望使用isActivityVisible()来检查活动是否可见。在那里,您还可以检查用户是否选择了选项。在满足两个条件时继续。