How to retain fragment state, when it's reopened by the deep link?

Viewed 106

I have one fragment page in android, the first time I open it, I get data from bundle and show. Now, when I go to web page from this page and come back by deep-link, I lose my current data (in other words, I have to go to the web page for payment, after that, I have to come back to the current fragment by deep link without losing current data)

2 Answers

Recently, I've been faced with a the same problem. I'm still a bit newbie in Android, so it's possibly not the best way to do it, but it does work.

First, in the Android Manifest, we have to add the attribute android:launchMode="singleTop" to the Activity that's hosting the Fragment. This way, when we go back to the app via deep link, the old Activity will receive the Intent instead of creating a new instance.

Then, in the code of the hosting Activity, we use the onNewIntent() method to look for the existing attached Fragment. As Hossein Kurd pointed out in his answer, this step depends on how we are managing our Fragments. In my case, I'm using a NavHostFragment, so first I have to find that and then I can search for the Fragment I want to come back to (in my case, an instance of LoginFragment):

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    if (intent != null && intent.action == Intent.ACTION_VIEW && intent.data != null) {
        val navHostFragment = supportFragmentManager.fragments.find { fragment -> fragment is NavHostFragment }
        navHostFragment?.let { navHostFrag ->
            val loginFragment = navHostFrag.childFragmentManager.fragments.find { childFragment -> childFragment is LoginFragment }
            loginFragment?.let { loginFrag ->
                val bundle = bundleOf("uri" to intent.data)
                loginFrag.arguments = bundle
                val fragmentTransaction = loginFrag.parentFragmentManager.beginTransaction()
                fragmentTransaction.show(loginFrag).commit()
            }
        }
    }
}

This method will receive the Intent from the browser, with the corresponding data (in my case, the Uri). We wrap the data in a Bundle and pass that to the Fragment's arguments and then show() the Fragment.

Finally, in the onResume() method of the Fragment, we check if the arguments include the data we are expecting, then we can go on with our logic:

override fun onResume() {
    super.onResume()
    this.arguments?.get("uri")?.let { data ->
        // Your logic with the data you received from the browser
    }
}

You can use getInstance static method, Better way is update fragment from activity

and the solution depends on the way you call your fragments: SupportFragmentManager, NavController ...

get current fragment by view Id or ...

Kotlin:

    supportFragmentManager.primaryNavigationFragment?.childFragmentManager?.fragments?.forEach { fragment ->
        // fragment.onActivityResult(requestCode, resultCode, boundle)
        fragment.method(param1, param2)
    }
Related