PagerAdapter.notifyDataSetChanged不刷新片段

roy*_*oyB 17 android android-viewpager android-pageradapter

我的Activity包含a ViewPager和它的自定义Adapter扩展FragmentStatePagerAdapter.ViewPager包含3个片段

用于从ViewPager中删除片段的代码

MainActivity

public void deleteElement(){
    final int currentItem = mViewPager.getCurrentItem();
    mPagerAdapter.removeItem(currentItem);
    mPagerAdapter.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)

CustomPagerAdapter

private ArrayList<Item> data;
public void removeItem(int index){
        data.remove(index);
}
Run Code Online (Sandbox Code Playgroud)

删除中间Fragment(索引1)时:

  • data我删除正确的item.
  • 问题是我(我猜)Fragment3被删除后notifyDataSetChanged,当前Fragment仍然是用户看到的片段,正在加载的数据来自SavedInstance捆绑

所以最终的结果是用户仍然看到Fragment他试图删除的相同,这对他来说有点不好意思.

想法?

kel*_*cer 28

尝试添加此:

private class MyPagerAdapter extends FragmentStatePagerAdapter {

//... your existing code

    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 但那么它会导致android重新启动我的所有碎片,这有点毫无意义吗? (2认同)
  • 我知道这两个选项,我在问这个问题之前就看过那些帖子.问题是我没有更新视图但是删除了一个视图.我无法确定哪个视图将被删除因此,逐个标记调用并不是真的安全(可能它已经被破坏了?我应该更新所有其他片段吗?) (2认同)

and*_*guy 5

您别无选择,只能执行PagerAdapter#getItemPosition。查看源代码,这正是ViewPager确定如何更新其位置,添加新片段或在之后添加死片段的方式notifyDataSetChanged。不必太难,您只需要访问传递的片段的状态,还需要访问保存订单的活动中的主状态。

还要求您实现getItemId为每个片段返回一致的ID,因为它们可以重新排序。

这就是我在照片的ViewPager中处理它的方式。

    private inner class PhotoPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
    override fun getItem(position: Int): PhotoViewFragment {
        // getItem is called to instantiate the fragment for the given page.
        return PhotoViewFragment.newInstance(position, this@PhotoPagerActivity.photos[position])
    }

    override fun getItemId(position: Int): Long {
        return this@PhotoPagerActivity.photos[position].ID!!.hashCode().toLong()
    }

    override fun getItemPosition(`object`: Any): Int {
        val frag = `object` as PhotoViewFragment
        val idx = this@PhotoPagerActivity.photos.indexOfFirst { ph -> ph.ID == frag.dataBinding.photo.ID }
        return if (idx >= 0) idx else PagerAdapter.POSITION_NONE
    }

    override fun getCount(): Int {
        return this@PhotoPagerActivity.photos.size
    }
}
Run Code Online (Sandbox Code Playgroud)


Yve*_*erm 4

我知道这个问题有点老了,但知道 Google 最近用ViewPager2解决了这个问题可能会很有趣。请参阅此处的示例

首先,您的 build.gradle 文件中有以下依赖项:

  dependencies {
     implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
  }
Run Code Online (Sandbox Code Playgroud)

现在您可以将 xml 文件中的 ViewPager 替换为:

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
Run Code Online (Sandbox Code Playgroud)

然后您需要在活动中将 ViewPager 替换为 ViewPager2

ViewPager2 需要 RecycleView.Adapter 或 FragmentStateAdapter :

    public class TabAdapter extends FragmentStateAdapter {
        private final List<Tab> tabs;

        public TabAdapter(@NonNull FragmentManager fm, List<Tab> tabs, Lifecycle lifecycle) {
            super(fm, lifecycle);

            this.tabs = tabs;
        }

        @NonNull
        @Override
        public Fragment createFragment(int position) {
            //create your fragment here
        }

        @Override
        public int getItemCount() {
            return tabs.size();
        }

        @Override
        public long getItemId(int position) {
            // use a distinct id for each item to allow the adapter to see the changes
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果您使用 TabLayout,则可以使用 TabLayoutMediator :

        TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager, true, new TabLayoutMediator.OnConfigureTabCallback() {
            @Override
            public void onConfigureTab(@NotNull TabLayout.Tab tab, int position) {
                // configure your tab here
                tab.setText(tabs.get(position).getTitle());
            }
        });

        tabLayoutMediator.attach();
Run Code Online (Sandbox Code Playgroud)

为了删除数据,从集合中删除项目后,您可以调用该notifyDataSetChanged()方法,或更具体地说,notifyItemRemoved()使用已删除项目的位置调用该方法