Допустим, у меня есть Activity
только с FrameLayout
(я также пробовал с новым FragmentContainerView
), поэтому я буду загружать на него Fragments
. Предположим, у меня есть два фрагмента: fragA и fragB. Сначала я загружу fragA и с помощью кнопки, присутствующей в этом фрагменте, < em>замените на fragB.
Я определил функцию для своего Activity
, чтобы я мог загрузить новый Fragment
в контейнер:
public void loadFragment(Fragment fragment) {
FragmentTransaction fragTrans = getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(null);
fragTrans.commit();
}
И я вызову это из fragA, чтобы перейти к fragB. Пока все хорошо, все работает. На самом деле проблема, с которой я сталкиваюсь, связана не с работой, а с тем, что мне не нравится время загрузки fragB, оно занимает около 2 секунд, и я хотел бы отобразить загрузку для пользователя, но я не могу этого добиться.
Первое, что я попробовал, это добавить gone ProgressBar
в макет действия, где находится контейнер. Затем моя функция loadFragment
сначала сделает видимым этот progressBar, а затем выполнит транзакцию фрагмента, и каждый фрагмент скроет (уйдет) это представление перед выходом из метода onCreateView
. Но проблема в том, что пользователь никогда не видит этот ProgressBar
, это похоже на то, что основной пользовательский интерфейс замораживается при рендеринге макета fragB и, следовательно, не обновляет пользовательский интерфейс, делая этот progressBar бесполезным. Я даже вижу некоторые пропущенные кадры в LogCat около 50 кадров.
В обоих фрагментах нет никакой логики, только onCreateView
реализовано там, где макет раздут. Я могу заметить, что если я изменяю макет fragB на более простой, он загружается мгновенно, поэтому я предполагаю, что проблема связана со временем, которое требуется для рендеринга макета. Этот тяжелый макет представляет собой действительно большую форму с большим количеством TextInputLayout
с TextInputEditText
и MaterialSpinner
(из GitHub).
Я знаю, что могу упростить макет, но я хотел бы знать, как я могу отображать загрузку во время рендеринга. Например, я видел, как некоторые приложения загружали какое-то фиктивное представление во время загрузки, а затем заменяли его реальными данными.
Я попробовал загрузить фиктивный макет с ProgressBar
посередине и в методе onCreateView
опубликовать Handler
, чтобы раздуть настоящий макет в том же контейнере в фон примерно такой:
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, чтобы я мог сказать, какой настоящий фрагмент я хочу отобразить. Этот промежуточный фрагмент не будет добавлен в стопку.
Как вы решаете такого рода проблемы?
Handler
и удалением всех представлений в методе onDestroyView. Но мне кажется некрасивым - person sebasira   schedule 04.04.2020