NotifyDataSetChanged 在带有 Viewpager2 的 FragmentStateAdapter 中不起作用

Sak*_*pta 4 android android-fragments android-viewpager fragmentstateadapter

我正在使用带有 FragmentStateAdapter 的 viewpager2 制作文件选择页面。在其中一个页面中,我显示了所有已安装的存储设备,我想点击这些设备来查看内容,但我希望内容位于另一个片段上。

我想用viewpager最后一页中的另一个片段替换片段。但是使用以下代码,页面只会刷新,并且不会创建新的 Fragment,因为createFragment不会被调用。

我的寻呼机适配器

public static class PagerAdapter extends FragmentStateAdapter {


        private Fragment mFragmentAtPos0;
        private final FragmentManager mFragmentManager;
        private final FirstPageListener listener = new FirstPageListener();
        public final class FirstPageListener implements
                FirstPageFragmentListener {
            public void onSwitchToNextFragment() {
                mFragmentManager.beginTransaction().remove(mFragmentAtPos0)
                        .commit();
                if (mFragmentAtPos0 instanceof FilesandFolder_Others_MainPage){
                    mFragmentAtPos0 = new FileExplorer(listener);
                }else{ // Instance of NextFragment
                    mFragmentAtPos0 = new FilesandFolder_Others_MainPage(listener);
                }
                notifyDataSetChanged();
            }
            public void onSwitchToNextFragment(Bundle bundle) {
//                mFragmentManager.beginTransaction().remove(mFragmentAtPos0)
//                        .commit();
                if (mFragmentAtPos0 instanceof FilesandFolder_Others_MainPage){
                    mFragmentAtPos0 = new FileExplorer(listener);
                    mFragmentAtPos0.setArguments(bundle);
                }else{ // Instance of NextFragment
                    mFragmentAtPos0 = new FilesandFolder_Others_MainPage(listener);
                    mFragmentAtPos0.setArguments(bundle);
                }
                notifyDataSetChanged();
//                notifyItemChanged(getItemPosition(mFragmentAtPos0));
            }
        }


//        @Override
//        public void onBindViewHolder(@NonNull FragmentViewHolder holder, int position, @NonNull List<Object> payloads) {
//            super.onBindViewHolder(holder, position, payloads);
//            if (position == getItemPosition(mFragmentAtPos0)) {
//
//                Fragment f = mFragmentManager.findFragmentByTag("f" + holder.getItemId());
//                if (f != null) {
//                    mFragmentManager.beginTransaction().replace(holder.getItemId(), )
//                }
//            }
//        }

        private int getItemPosition(Fragment mFragmentAtPos0) {
            for (int i = 0; i < getItemCount(); i++){

                if (createFragment(i).equals(mFragmentAtPos0)){
                    return i;
                }
            }
            return -1;
        }


        public PagerAdapter(FragmentActivity fm) {
            super(fm);
            mFragmentManager = fm.getSupportFragmentManager();
            mFragmentAtPos0 = new FilesandFolder_Others_MainPage(listener);
        }

        @NonNull
        @Override
        public Fragment createFragment(int position) {
            switch (position){
                case 0:
                    return new AppSelectionFragment();
                case 1:
                    return new Photos();
                case 2:
                    return new VideoGalleryFragment();
                case 3:
                    return new Gallery();
                default:
                    return mFragmentAtPos0;
            }
        }

        @Override
        public int getItemCount() {
            return 5;
        }
    }

Run Code Online (Sandbox Code Playgroud)

这是 Fragment 的构造函数,我想从中替换为另一个 Fragment:

    private static FileSelection.PagerAdapter.FirstPageListener pageFragmentListener;

    public FilesandFolder_Others_MainPage() {
    }
    public FilesandFolder_Others_MainPage(FileSelection.PagerAdapter.FirstPageListener firstPageFragmentListener) {
        pageFragmentListener = firstPageFragmentListener;
    }

Run Code Online (Sandbox Code Playgroud)

在点击视图时,应该调用以下代码:-

Bundle bundle = new Bundle();
bundle.putString("PATH", volumes.get(position).path);
pageFragmentListener.onSwitchToNextFragment(bundle);
Run Code Online (Sandbox Code Playgroud)

我已经在整个 stackoverflow 上进行了搜索,但从未看到 viewpager 2 和 FragmentStateAdapter 的正确答案,因为每个人似乎都在使用 Viewpager

我试图实现这个:-FragmentStateAdapter for ViewPager2 notifyItemChanged 没有按预期工作

但无法理解如何编辑我的代码。请帮助提前致谢

小智 5

有同样的问题,这就是我发现的:

FragmentStateAdapterhas method onBindViewHolder(holder, position, payloads),您可以覆盖它(与onBindViewHolder(holder, position)final不同)。当你调用这个方法调用notify的方法,以及notifyItemChanged()notifyItemRangeChanged()方法可以访问片段,并手动更新。

这是访问片段的代码:

public void onBindViewHolder(@NonNull FragmentViewHolder holder, int position, @NonNull List<Object> payloads) {

    String tag = "f" + holder.getItemId();

    Fragment fragment = fragmentManager.findFragmentByTag(tag);

    if (fragment != null) {
        //manual update fragment
    } else {
        // fragment might be null, if it`s call of notifyDatasetChanged() 
        // which is updates whole list, not specific fragment
        super.onBindViewHolder(holder, position, payloads);
    }
}
Run Code Online (Sandbox Code Playgroud)

FragmentStateAdapter被标记为他的片段"f" + holder.getItemId(),这就是它起作用的原因。

你也可以使用DiffUtil,这是更好的方法。这是解决这个问题的好例子,最后还有一些链接,以便更好地理解ViewPager2.