【问题标题】:PagerAdapter changed adapters content with notifyingPagerAdapter 通过通知更改了适配器内容
【发布时间】:2017-09-24 15:03:18
【问题描述】:

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

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

我的数据太大而无法通过 Intent 传输(使用 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 类型布局的更好方法有任何建议,我将不胜感激它。

【问题讨论】:

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


    【解决方案1】:

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

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

    编辑:

    Activity 案例:如果目标 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" >
    

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

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

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

    【讨论】:

    • 那个方法是什么类的一部分?我提到的所有类都没有覆盖该方法。(编辑:谷歌说它连接到一个片段,我没有在任何地方使用片段)
    • @rycirese 您的浏览器屏幕中的课程类型是什么?我通常将这种方法用于我的Fragment。你的听起来像你在使用Activity
    • 正确,所有这个活动都是一个viewpager。
    • 我认为我的问题是我的DataTransferer 类中存储的List&lt;&gt; 与我的第一个活动的引用相同,当我通过网络加载并开始第二个活动时,我从DataTransferer 中获取List&lt;&gt;。在网络完成并更新列表之间的某个地方,但由于我无法从第二个活动中检查这一点,因此适配器不会收到更改通知。我将尝试在DataTransferer 类中实现某种回调监听器处理,以在列表更新时通知第二个活动。
    • @rycirese 我刚刚更新了我的答案以检测您的活动是否可见
    猜你喜欢
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多