Sunday, May 10, 2020

Best Practice for Handling Back Hard/Soft Navigation for Fragments - Kotlin/Java Android

So I was getting this question from my viewers for handling the back/soft press on Android App. See there are many ways to handle this but every app has nowadays followed a Design-Patterns like MVC, MVP, MVVM, REDUX, etc. So how to implement the back navigations which work smoothly. I will try to give you a complex use-case So that you can relate to it. But let's assume you have created an Android Project with 2 Activities and Say 20 fragments in it.

So suppose it is like below

Activity1 hosting 10 fragments and then Another Activity2 hosting another 10 fragments So now how to design you back navigation for this use case.

For Fragments and Back Navigation Google App Developer site have a well-defined article but you have to understand it in order to implement below is the URL of it in case you wish to see.



So suppose you have Designed your app code structure like you know you have BaseActivity and BaseFragment and you are defining all the functions withing it and obviously implementing those in your Activity1 and Activity2 right So far with me?

The same goes for Fragments to Since you have Base Fragments So you must be doing like below I am giving example.

This is pretty basic Java/Kotlin but actually quite essential for any fragment-heavy application. I find this leads to less code complexity but more extensibility for me. I have a standard container layout in XML, and call the following to the swap fragments in it:

Fragment myNiceFragment = MyNiceFragment.instantiate(mContext, MyNiceFragment.class.getName(), args);

getSupportFragmentManager().beginTransaction()
        .replace(R.id.content_container, myNiceFragment, myNiceFragment.getClass().getSimpleName())
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        .addToBackStack(null)
        .commit();

For committing fragments you must be doing like above this is just a code snippet to make you understand how to do it? Do not confuse between Add/Replace/Remove of fragments right?
Of course, by adding it to the back stack it pops when we press back by default, which is just lovely.  user hits back, and not just have the hosting activity know that we pressed back. He should share that info with anyone that would like to know!.

Solution

To tell fragments when the back button has been pressed, first of all, you need a base fragment which all of your other fragments inherit from. This base fragment implements the following:

BaseFragment.Java/BaseFragment.kt: whichever way you prefer.

public interface OnBackPressed {
    void onBackPressed();
}

public class BaseFragment extends Fragment implements OnBackPressed {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    public void onBackPressed() {//Leave it empty}
}

Now in your hosting Activity, call any implementations of the interface before any fragments are popped:

Just do this in your Hosting Activit1 and Activity2 and You are good to go.No problem at all.

@Override
public void onBackPressed() {
    tellFragments();
    super.onBackPressed();
}

private void tellFragments(){
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for(Fragment f : fragments){
        if(f != null && f instanceof BaseFragment)
            ((BaseFragment)f).onBackPressed();
    }
}

That’s it! Any fragments which implement our onBackPressed() can do so and will be told as soon as the Activity is.

In Your Respective Fragments:

@Override
public void onBackPressed(){
    getActivity().getSupportFragmentManager().popBackStack();
}


So what are the Pros and Cons implementing this way if you see Suppose you have a requirement like when press back from Fragment 10 and I should Navigate to Fragment 2 Right? So it is just easy like in you on the BackPress method write a while loop and put a condition and just make a fragment Pop call and you are good. This type of requirement you will find in almost all your project So I find this way you are more controlled and maintained and once you leave the company your fellow Developer can understand it too :). I saw many people end up doing it in Activiting making switch cases and handling there believe me at some point in time the code becomes impossible to understand for a big project. So this one is the best way to do it. let me know your thoughts on it.

Note Just little tweak to make it compatible with Kotlin is just do it like below:

interface OnBackPressed {
    fun onBackPressed();
}

I hope you understand it and if you are not able to d to it just copy and paste this code and Android Studio will do it for you.

Thanks.





No comments: