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.