PagerAdapter.notifyDataSetChanged不刷新碎片

PagerAdapter.notifyDataSetChanged does not refresh fragments

我的 Activity 包含一个 ViewPager 并且它是扩展 FragmentStatePagerAdapter 的自定义 AdapterViewPager 包含 3 个片段

从 ViewPager 中删除片段的代码

MainActivity

public void deleteElement(){
    final int currentItem = mViewPager.getCurrentItem();
    mPagerAdapter.removeItem(currentItem);
    mPagerAdapter.notifyDataSetChanged();
}

CustomPagerAdapter

private ArrayList<Item> data;
public void removeItem(int index){
        data.remove(index);
}

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

因此,用户仍然看到他试图删除的相同 Fragment 的最终结果,这对他来说有点糟糕。

想法?

***** 编辑 ******

似乎 ViewPager2 可以解决这个问题以及许多其他问题

尝试添加这个:

private class MyPagerAdapter extends FragmentStatePagerAdapter {

//... your existing code

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

}

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

还需要您实施 getItemId 到 return 每个片段的一致 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
    }
}

您可以尝试使用 FragmentPagerAdapter 而不是 FragmentStatePagerAdapter。问题是,我也 运行 关注这个问题,它帮助了我。

您必须先将适配器设置为空,然后再将其设置回去:

int currentPosition = mViewPager.getCurrentItem();
mPagerAdapter.notifyDataSetChanged();
mViewPager.setAdapter(null);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(currentPosition);

您可以尝试使用 FragmentStatePagerAdapter 而不是 FragmentPagerAdapterpublic

它对我有用..!

我知道这个问题有点老了,但是知道 Google 最近用 ViewPager2. See examples here

解决了这个问题可能会很有趣

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

  dependencies {
     implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
  }

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

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

然后您需要将 activity

中的 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
        }
    }

如果您使用的是 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();

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

区分片段然后android系统将负责回收片段。

例如 - 覆盖 getItemId 提供唯一 ID。

FragmentStateAdapter (ViewPager2) - Kotlin 版本。

class HomeViewPagerAdapter(
fa: FragmentActivity
) : FragmentStateAdapter(fa) {

lateinit var fragments: ArrayList<Fragments>

override fun getItemCount(): Int {
    return fragments.size
}

override fun getItemId(position: Int): Long {
    return fragments[position].id.ordinal.toLong()
}
override fun createFragment(position: Int): Fragment {
    return fragments[position].fragment
}
}
data class Fragments (val id: FragmentId, val fragment: Fragment)
enum class FragmentId {
    PageOne, 
    PageTwo,
    PageThree
}

更新适配器

    private fun setupAdapter(fragments: ArrayList<Fragments>) {
    if (adapter != null) {
        adapter?.fragments = fragments
        adapter?.notifyDataSetChanged()
    } else {
        adapter = HomeViewPagerAdapter(requireActivity())
        adapter?.fragments = fragments
        binding.homeViewPager.adapter = adapter
        binding.locationDisabledLl.setOnClickListener {
            findNavController().navigate(HomeFragmentDirections.actionHomeToPermission())
        }
    }
}