Оптимизация Viewpager с помощью пользовательских представлений - PullRequest
0 голосов
/ 31 октября 2019

Сценарий - Я работаю над приложением, которое показывает события, относящиеся к определенным датам, в окне просмотра, где каждая страница представляет день (то есть 24 часа по вертикали, как в календаре Google). Каждая страница / фрагмент содержит вертикальный вид прокрутки (внутри него есть структура кадра), и на основе списка событий я динамически создаю пользовательские виды (позиция и измерение вида зависят от соответствующего времени и продолжительности события) и добавляю его в вид прокрутки. , Пользователь может перетаскивать события между датами.

Проблема - Я успешно выполнил часть создания представления, теперь проблема связана с производительностью. Иногда vewpager (используя FragmentStatePagerAdapter) задерживается при перелистывании страниц.

Кто-то, пожалуйста, подскажите мне, как уменьшить задержку или какие-либо более эффективные способы достижения этого

1 Ответ

0 голосов
/ 31 октября 2019

Да, у меня была похожая производительность с viewpager и FragmentStatePagerAdapter, проблема с viewpager заключается в том, что pre создает представления по обе стороны от текущего представления, чтобы ускорить пролистывание до следующего представления.

Это хорошо работает для статическогопредставления, но для представлений с динамическими данными, предварительно созданное представление, как правило, устарело и должно было быть восстановлено, когда пользователь проводил по нему.

Таким образом, ему приходилось вызывать onCreateView для 3 представлений, пока пользовательпролистывал между видами, что иногда приводило к отставанию.

Я думал о 2 улучшениях производительности, хотя использовал только одно.

1) Держатель вида / модель, например https://www.androidcode.ninja/android-viewholder-pattern-example/ и https://developer.android.com/topic/libraries/architecture/viewmodel, где инфляция и нахождение предметов повторно использовались / отделены от onCreateView действий.

Я не использовал этот метод

2) Создайте голые представления для динамических(Первое представление было статичным, а затем в позициях 1 и 2 было 2 динамических представления, которые содержали списки различных аспектов динамических данных.)

Списки просмотра были раздуты, и в onCreateView этих представлений для адаптера был установлен пустой список, поэтому они быстро создавались.

Затем я добавил OnPageChangeListener, который уведомил adapterподдержка ViewPager, что страницы изменились

        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {

                if (position == 1 || position == 2)
                {
                    mSectionsPagerAdapter.notifyDataSetChanged();
                }
            }
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // Code goes here
            }
            @Override
            public void onPageScrollStateChanged(int state) {
                // Code goes here
            }
        });

notifyDataSetChanged заставляет viewPager вызывать getItemPosition в классе FragmentStatePagerAdapter, если изменилась позиция страницы, и если нужновоссоздать его в новой позиции.

Затем в FragmentStatePagerAdapter расширенном классе я переопределил getItemPosition с помощью

@Override
        public int getItemPosition(Object object) {
            if (object instanceof LogFragment) {
                LogFragment f = (LogFragment) object;
                if (f != null) {
                    f.update();
                }
            } else if (object instanceof SummaryFragment){
                SummaryFragment f = (SummaryFragment) object;
                if (f != null) {
                    f.update();
                }
            } else {
                return POSITION_UNCHANGED;
            }
            return super.getItemPosition(object);
        }

Это позволило мне получить объект Fragment и затем вызватьметод update для него, но по-прежнему возвращает POSITION_UNCHANGED, поэтому просмотрщик не пытался воссоздать фрагменты.

Затем в методе update фрагмента я получаю адаптер списка и обновляюdata.

public void update(){
        adapter.clear();
        adapter.addAll(datasource.getData());
    }

Таким образом, более дорогостоящие получение и отображение динамических данных выполняются только тогда, когда страница действительно отображается, а НЕ когда она предварительно создается viewPager (потому что это предварительно созданное представление будет старымустарел dв любом случае и потребуется обновление)

У этого подхода есть один недостаток: экран, отображаемый во время , до сих пор остаются старые данные (либо пустые, либо данные, полученные с этой страницы). последнее обновление), это было приемлемо для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...