Как раздуть макет фрагмента в AppCompatActivity.onCreate ()? - PullRequest
1 голос
/ 01 февраля 2020

Я создаю простое приложение для изучения фрагментов. Он состоит из bottomNavigationView с тремя пунктами меню и FrameLayout, который служит контейнером для фрагментов и занимает остальное пространство. Выбор элемента переключает фрагмент в FrameLayout с помощью:

getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer,selectedFragment).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).commit();

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

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if(ui == null)
            inflateLayout(inflater, container);
        return ui;

    }

Это частично исправило проблему, потому что первый переход все еще был медленным. Я пытался раздуть пользовательский интерфейс фрагмента в действии, но это привело к ошибке: фрагмент не привязан к контексту. Так что я просто переключился между всеми фрагментами в onCreate () основного действия:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    BottomNavigationView nav = findViewById(R.id.bottom_nav);
    homeFragment = new HomeFragment();
    favFragment = new FavFragment();
    starFragment = new StarFragment();
    nav.setSelectedItemId(R.id.home);
    getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer, starFragment).commit();
    getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer, favFragment).commit();
    getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer, homeFragment).commit();
    nav.setOnNavigationItemSelectedListener(listener);
}

Это улучшило ситуацию, но recyclerView, который содержится в StarFragment, все еще создает viewHolders после «реальной» транзакции (инициированной слушателем). ), что занимает 20 мс для одного viewHolder (я выясню почему позже).

Мой вопрос: как сделать эти транзакции между фрагментами быстрыми? Что я пытаюсь сделать правильно, или есть лучший способ?

1 Ответ

1 голос
/ 01 февраля 2020

Я не уверен, насколько сложны ваши макеты, однако загрузка элементов пользовательского интерфейса в макет фрагмента не займет много времени, если загрузчики данных (чтение значений для вашего RecyclerView из базы данных, сетевые вызовы) отключены -threaded.

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

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

Вот хороший урок о том, как добавить ViewPager с нижней панелью навигации. Я надеюсь, что это помогает!

...