Viewpager для обновления только текущего видимого фрагмента - PullRequest
0 голосов
/ 19 марта 2020

я обновляю recycleView внутри viewpager fragments и вызываю pagerAdapter.notifyDataSetChanged();, чтобы обновить их. Он обновляет все recycleviews и приложение занимает много времени. Теперь, чтобы решить эту проблему, я хочу обновить только текущий видимый фрагмент, а при изменении 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;
                }
           }
        }
    }

1 Ответ

1 голос
/ 19 марта 2020

Извините, это немного бессмысленный ответ, но приведенного примера кода недостаточно, чтобы дать работающий ответ, поэтому более реально пытаться объяснить концепцию. Действительно нужны подробности того, когда и как обновляются данные, НО ...

Поскольку вы используете 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)

Тогда все фрагменты будут переведены в «Запущено» только при создании или повторном создании и только текущее на экране с «Возобновлено» и затем «Приостановлено» при перемещении с экрана.

Точная механика зависит от того, как представления рециркулятора фрагментов получают свои данные и что запускает обновление, но тогда общая идея заключается в том, чтобы фрагменты onCreateView создали легкую «оболочку» макета, у меня в основном есть кнопки / текст stati c и создайте просмотр рециркулятора с пустым набором данных.

Затем в методе onResume фрагмента, который вызывается только для фрагмента, в настоящее время находящегося на Sc Затем он вызывает ваш метод update, чтобы заменить два пустых набора данных в представлении реселлера фактическим набором данных, и делает notifyDataSetChanged() для обзоров рециркулятора.

Поэтому, когда пейджер изначально создается, создается X количество фрагментов и там stati c содержимое выложено плюс 1 фрагмент (текущий на экране) получает представление переработчика, заполненное фактическими данными.

Затем вы можете также включить некоторые проверки оптимизации в onResume фрагмента проверить, действительно ли изменились данные представлений в режиме просмотра обзоров (простая проверка размера или использование DiffUtils в Recyclerview), иначе при перемещении между фрагментами в окне просмотра каждый фрагмент будет приостановлен / возобновлен.

Это действительно только задерживает стоимость два повторных просмотра в фрагменте до тех пор, пока они действительно не понадобятся (когда он будет отображаться), это форма «отложенной загрузки»

с перемещением данных «dynamici c» в эту «отложенную загрузку» "Это может быть возможно, чтобы удалить необходимость notifyDataSetChanged на Фра Но пока фрагменты кода недостаточно показывают, как и почему меняется содержимое вьюверлера.

При использовании этого метода изменяются данные при рисовании, и вам может не понравиться их внешний вид.

Это действительно на высоком уровне инверсия логики обновления фрагментов c, вместо того, чтобы сказать: «Данные изменились, перерисовать данные во всех фрагментах», это «Этот фрагмент показан, перерисовать данные, ЕСЛИ он был» изменилось с тех пор, как я нарисовал в последний раз "

...