【问题标题】:Viewpager to update only current visible fragmentViewpager 仅更新当前可见片段
【发布时间】:2020-03-18 21:49:50
【问题描述】:

我在viewpager fragments 中更新recycleView 并调用pagerAdapter.notifyDataSetChanged(); 来更新它们。它会更新所有回收视图,并且该应用程序需要很长时间。现在为了克服这个问题,我只想更新当前可见的片段,并在 ViewPage 更改时用notifyDataSetChanged(); 更新其他片段有没有办法告诉更新哪个片段?

ViewPagerAdapter

 private class MyPageAdapter extends FragmentStatePagerAdapter {
            private List<Fragment> fragments;
            private int[] mResources;

        public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
            super(fm);
            this.fragments = fragments;
        }

        @Override
        public Fragment getItem(int position) {

            return this.fragments.get(position);

        }

        @Override
        public int getCount() {
            return this.fragments.size();
        }

        @Override
        public int getItemPosition(Object object) {
            MyFragment f = (MyFragment) object;
            if (f != null) {
                f.update();
            }
            return super.getItemPosition(object);
        }
    }

这是片段

public static class MyFragment extends Fragment implements CustomAdapterOdds.OnGameClickListener, Updateable {
        public static final String COLUMN_IN_DISPLAY = "column_in_display";


        RecyclerView recyclerView, recyclerView2;
        HashMap<String, List<OddsFeed>> oddsList1;
        HashMap<String, List<OddsFeed>> oddsList2;
        int oddsColDisp;
        CustomAdapterOdds adapterOdds1, adapterOdds2;

        boolean isvisible = false;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {

            oddsList1 = new HashMap<>();
            oddsList2 = new HashMap<>();
            Bundle b = this.getArguments();
            oddsColDisp = b.getInt(COLUMN_IN_DISPLAY);
            List<GameFeed> leftGames = getArguments().getParcelableArrayList("list");
            if (b.getSerializable("hashmap1") != null && b.getSerializable("hashmap2") != null) {
                oddsList1 = (HashMap<String, List<OddsFeed>>) b.getSerializable("hashmap1");
                oddsList2 = (HashMap<String, List<OddsFeed>>) b.getSerializable("hashmap2");
            }

            View v = inflater.inflate(R.layout.view_table_viewpager_fragment_layout, container, false);

            ArrayList<GameFeed> gameFeedsCol0 = getArguments().getParcelableArrayList("list");

            //recycleview1
            recyclerView = v.findViewById(R.id.table_view_recycle_view_odds1);
            adapterOdds1 = new CustomAdapterOdds(getContext(), leftGames, this, oddsList1, bestSitesList, oddsColDisp);
            configRecyclerViewOdds(getContext(), recyclerView, adapterOdds1);

            //recycleview2

            recyclerView2 = v.findViewById(R.id.table_view_recycle_view_odds2);
            adapterOdds2 = new CustomAdapterOdds(getContext(), leftGames, this, oddsList2, bestSitesList, oddsColDisp + 1, true);
            configRecyclerViewOdds(getContext(), recyclerView2, adapterOdds2);

            return v;
        }


        @Override
        public void setMenuVisibility(final boolean visible) {
            super.setMenuVisibility(visible);
            if (visible) {
                isvisible = true;
            }
        }

        @Override
        public void onResume() {
            super.onResume();
            Toast.makeText(getContext(), "onresume", Toast.LENGTH_SHORT).show();
            adapterOdds1.updateListOdds(leftGames, oddsList1, oddsColDisp);
            adapterOdds2.updateListOdds(leftGames, oddsList2, oddsColDisp + 1);

        }

        @Override
        public void OnGameClickListener(View view, int position) {

        }

        @Override
        public void update() {

            Toast.makeText(getContext(), "update", Toast.LENGTH_SHORT).show();
            if (isVisible()) {
                adapterOdds1.updateListOdds(leftGames, oddsList1, oddsColDisp);
                adapterOdds2.updateListOdds(leftGames, oddsList2, oddsColDisp + 1);
             updateViewpager++;
                int size = bestSitesList.size() / 2;

                adapterOdds1.updateListOdds(leftGames, oddsList1, oddsColDisp);
                adapterOdds2.updateListOdds(leftGames, oddsList2, oddsColDisp + 1);

                if (updateViewpager == size - 1) {
                    progressBar.setVisibility(View.INVISIBLE);
                    updateViewpager = 0;
                }
           }
        }
    }

【问题讨论】:

  • 您使用的是什么版本的 Viewpager(您使用的是什么支持库/androidx 版本)?由于 viewpager 中使用的 Fragment 生命周期状态发生了变化。
  • 是的,我正在使用 androidx @Andrew

标签: android android-fragments android-viewpager


【解决方案1】:

很抱歉,这是一个有点漫不经心的答案,但没有提供足够的代码示例来做出有效的答案,所以更多的是真正试图解释一个概念。确实需要有关何时以及如何更新数据的详细信息,但是...

当您使用 androidx 时,您可能需要考虑迁移到 viewpager2 或使用 viewpager,您可以更改片段生命周期状态的管理方式。

如果您在构建适配器时改为使用BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT https://developer.android.com/reference/androidx/fragment/app/FragmentStatePagerAdapter#BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT https://developer.android.com/reference/androidx/fragment/app/FragmentStatePagerAdapter#FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager,%20int)

然后,所有片段将仅在创建或重新创建时显示为“已启动”,并且只有当前片段在屏幕上显示为“恢复”,然后在移出屏幕时显示为“暂停”。

确切的机制取决于 Fragments recyclerviews 如何获取他们的数据以及触发更新的原因,但一般的想法是让 Fragments onCreateView 创建一个轻量级的布局“外壳”,我基本上有静态按钮/文本并使用空数据集创建回收站视图。

然后在 Fragment 的 onResume 方法中,该方法仅针对当前屏幕上的 Fragment 调用,它调用您的 update 方法以用实际数据集替换两个 recyclerview 的空数据集,并在 recyclerviews 上执行 notifyDataSetChanged() .

因此,当最初创建 viewpager 时,会创建 X 个 Fragment,并在其中布置静态内容,再加上 1 个 Fragment(屏幕上的当前一个 Fragment),recyclerview 会填充实际数据。

然后,您可能还想在片段的onResume 中进行一些优化检查,以检查 recyclerview 视图数据是否已实际更改(简单的大小检查或使用 Recyclerview 的 DiffUtils),否则当您在 viewpager 中的片段之间移动时每个 Fragment 都会暂停/恢复。

这真的只是延迟Fragment中两个recyclerview的开销,直到真正需要(即将显示时),是一种“延迟加载”的形式

通过将“动态”数据移动到此“延迟加载”,可以消除片段上 notifyDataSetChanged 的需要,但代码 sn-ps 没有充分说明 recyclerviews 内容如何以及为何发生变化.

使用此方法,当绘制数据时发生更改,您可能不喜欢它的外观。

这实际上是片段更新逻辑的反转,而不是说“数据已更改,重绘所有片段中的数据”,而是“显示此片段,如果已显示则重绘数据自从我上次画它以来发生了变化”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多