PagerAdapter.notifyDataSetChanged不刷新片段

时间:2015-01-23 18:48:41

标签: android android-viewpager android-pageradapter

我的Activity包含ViewPager及其自定义Adapter,其中包含FragmentStatePagerAdapterViewPager包含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)时:

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

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

想法?

7 个答案:

答案 0 :(得分:26)

尝试添加此内容:

private class MyPagerAdapter extends FragmentStatePagerAdapter {

//... your existing code

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

}

答案 1 :(得分:4)

您别无选择,只能实施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
    }
}

答案 2 :(得分:1)

我知道这个问题有点老了,但是知道Google最近用ViewPager2解决了这个问题可能会很有趣。查看示例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" />

然后您需要在活动中将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()并指定已删除项目的位置

答案 3 :(得分:0)

您可以尝试使用FragmentPagerAdapter而不是FragmentStatePagerAdapter。问题是,我也遇到过这个问题,它帮助了我。

答案 4 :(得分:0)

您必须首先将适配器设置为null,然后再将其重新设置:


Processed Vade Retro 01.394.21 AS+AV+AP+RT Profile: OVH; Bailout: 300; ^ForbiddenHdr (500)

答案 5 :(得分:0)

区分Fragment,然后android系统会负责回收这些Fragment。

例如 - 覆盖 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())
        }
    }
}

答案 6 :(得分:-1)

您可以尝试使用FragmentStatePagerAdapter代替FragmentPagerAdapter public

它对我有用..!