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?
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 !