Android Фрагмент отображения загрузки при рендеринге макета - PullRequest
0 голосов
/ 04 апреля 2020

Допустим, у меня есть Activity только с FrameLayout ( Я также попробую с новым FragmentContainerView), поэтому я буду загружать Fragments на нем. Давайте предположим, что у меня есть два фрагмента: fragA и fragB , я сначала загружу fragA и с помощью кнопки, присутствующей в этом фрагменте, заменяем это с fragB .

Я определил функцию на моем Activity, чтобы я мог загрузить новый Fragment на контейнер:

public void loadFragment(Fragment fragment) {
    FragmentTransaction fragTrans = getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.container, fragment)
            .addToBackStack(null);

    fragTrans.commit();
}

И я назову это от fragA до go до fragB . Пока все хорошо, все работает отлично. На самом деле проблема, с которой я сталкиваюсь, заключается не в функционировании, а в том, что мне не нравится время загрузки fragB , оно занимает около 2se c, и я хотел бы отобразить загрузку в пользователь, но я не могу этого добиться.

Первое, что я попробую, это добавить ушел ProgressBar в макет действия, где находится контейнер. Тогда моя loadFragment функция сначала установит видимый этот progressBar, а затем выполнит транзакцию фрагмента, и каждый фрагмент будет скрывать ( исчез ) это представление перед выходом из метода onCreateView. Но проблема в том, что пользователь никогда не видит этот ProgressBar, это похоже на то, что основной пользовательский интерфейс зависает при рендеринге макета fragB и, следовательно, не обновляет пользовательский интерфейс, делая этот progressBar бесполезным. Я даже вижу пропущенных кадров в LogCat около 50 кадров.

Оба фрагмента не имеют лог c, только onCreateView реализован там, где раздувается макет. Я могу заметить, что если я изменю макет fragB на более простой, он загружается мгновенно, поэтому я предполагаю, что проблема связана со временем, которое требуется для визуализации макета. Этот тяжелый макет - действительно большая форма с большим количеством TextInputLayout с TextInputEditText и MaterialSpinner (от GitHub).

Я знаю, что, возможно, могу упростить макет, но я хотел бы знать, как я могу отобразить загрузку при рендеринге. Например, я видел, как некоторые приложения загружают какой-то dummy-view во время загрузки, а затем заменяют его реальными данными.

Одна вещь, которую я пробовал, это загрузить * 1060 макет * dummy с ProgressBar в середине и в методе onCreateView опубликуйте Handler, чтобы накачать real макет на тот же контейнер в фоновом режиме, например:

public View onCreateView(final LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_dummy, container, false);

    Handler mHandler = new Handler();
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            container.removeAllViews();
            View realView = inflater.inflate(R.layout.fragment_real, container);
        }
    });
}

Эта работа вроде бы приятна, так как просмотр приятен, но при переходе назад макет fragB остается видимым в качестве фона других фрагментов. Я не тестировал его, но, возможно, я смогу позвонить container.removeAllViews(); перед выходом из фрагмента, и он будет работать, но все равно мне кажется, что это обходной путь, а не решение.

И еще я не пробовал потому что, возможно, это избыточное уничтожение, это иметь промежуточный или , загружающий фрагмент, и загружать его всегда до реального фрагмента, и я передам Intent Extra для него, чтобы я мог сказать, что реальный фрагмент, который я хочу показать. Этот промежуточный фрагмент не будет добавлен в backstack.

Как вы решаете такие проблемы?

Ответы [ 2 ]

0 голосов
/ 05 апреля 2020

Ну, похоже, AsyncLayoutInflater - это путь к go!

Вот как я его использую:

private ViewGroup fragmentContainer;

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View dummyView = inflater.inflate(R.layout.fragment_dummy_loading, container, false);

    fragmentContainer = container;
    AsyncLayoutInflater asyncLayoutInflater = new AsyncLayoutInflater(getContext());


    asyncLayoutInflater.inflate(R.layout.fragment_real_layout, container, new AsyncLayoutInflater.OnInflateFinishedListener() {
        @Override
        public void onInflateFinished(@NonNull View view, int resid, @Nullable ViewGroup parent) {
            fragmentContainer.removeAllViews();
            fragmentContainer.addView(view);
        }
    });


    return dummyView;
}


@Override
public void onStop() {
    super.onStop();
    fragmentContainer.removeAllViews();
}

Там, фрагмент_думми_загрузки есть макет с ProgressBar и frag_real_layout - это действительно тяжелый макет.

Есть только одна вещь, которую я не получаю ... и как я могу связать объекты с XML widgets ( без использования Android Привязка данных, если возможно ) , когда AsyncLayoutInflater возвращается в инфальт в потоке пользовательского интерфейса.

Согласно документам:

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

И я проверяю источник AsyncLayoutInflater и я могу сказать, что метод onInflateFinished вызывается независимо от того, была ли инфляция в фоновом режиме или в основном потоке

0 голосов
/ 04 апреля 2020

Я думаю, что вы должны использовать AsycTask при загрузке нового фрагмента

1 - загрузить новый фрагмент

2 - запустить Asyn c задачу

3 - инициализировать Progressdialog в конструкторе AsyncTask, в который вы хотите загрузить данные

4 - Показать Progressdialog в onPreExecute () в AsyncTask с dialog.show ()

5 - Отклонить Progressdialog в onPostExecute () в AsyncTask с dialog.dismiss ()

6 - обновить пользовательский интерфейс / установить новые данные для вашего адаптера и т. д. c

Проверить здесь Показывать загрузочный спиннер во время фрагмента загружается

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