Home > Software engineering >  Fragment transition has slight delay when replacing fragment with another, how do I prevent it?
Fragment transition has slight delay when replacing fragment with another, how do I prevent it?

Time:12-26

I have a fragment A inside my activity. When I want to replace that fragment, I have a transition to move fragment A off screen and move fragment B onto the screen.

However, before fragment B is displayed, there is a slight lag/delay. I have narrowed down the problem to be my Recycler Adapter loading 5 or more items causing that 0.5 second lag (There is no lag when the Recycler has no items). It also only happens on the first loading of items.

I think it's because the adapter loading is taking about 0.5 seconds on the ui thread.

My question is, How can I design it so there is no more of that delay?

My Adapter is called inside the fragment's onViewCreated() but that doesn't seem to remove the delay.

@Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        viewModel = new ViewModelProvider(this).get(MainViewModel.class);

        adapter = new BackpackAdapter(viewModel.getListItems());
        recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
        recyclerView.setAdapter(backpackAdapter);
    }

I am also using Glide to load the images on a background thread but it doesn't seem to remove the delay either.

@Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int i) {
        Glide.with(holder.itemView.getContext())
                .load(list.get(i).getImage())
                .apply(RequestOptions.centerCropTransform())
                .into(holder.imageView);

        ...
        ...

This is my Fragment transition to take fragment A off screen to display B

getChildFragmentManager().beginTransaction()
                .setReorderingAllowed(true)
                .setCustomAnimations(R.anim.enter_right, R.anim.exit_left, R.anim.enter_left, R.anim.exit_right)
                .replace(R.id.container_view, new FragmentB(), "FRAG_B")
                .commit();

Does anyone know what I can do to make the Fragment Transition more smoothe?

CodePudding user response:

I had this problem too, and I solved that using postponeEnterTransition method of Fragment.

First you need to extend all your fragments from a base fragment like this:

public class HomeFragment extends BaseFragment {

}

Next create BaseFragment class like this:

public class BaseFragment extends Fragment {

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // we don't need to change transition animations when method calls again!
        if (savedInstanceState != null) return;

        // here we pause enter transition animation to load view completely
        postponeEnterTransition();

        // we set the background color of root view to white
        // because navigation animations run on a transparent background by default
        view.setBackgroundColor(Color.WHITE);

        // here we start transition using a handler
        // to make sure transition animation won't be lagged
        view.post(() -> postponeEnterTransition(0, TimeUnit.MILLISECONDS));
    }

}

FYI, I used navigation component, and to apply transition animations for all fragments I added these lines in styles:

<style name="Theme.AppName" parent="Theme.MaterialComponents.Light.NoActionBar">

        <item name="enterAnim">@anim/enter_anim</item>
        <item name="exitAnim">@anim/exit_anim</item>
        <item name="popEnterAnim">@anim/pop_enter_anim</item>
        <item name="popExitAnim">@anim/pop_exit_anim</item>

</style>

Note: if you are using LiveData for updating your recyclerView, it causes a lag in transition animation because it loads items asynchronously.

Hope this helps !

CodePudding user response:

You can utilize android ViewStub, which helps in lazily loading views, You can put your recyclerview as viewstub, so that it loads lazily, and recyclerview loading does not delay fragment transition.

  • Related