1

Hey I am working on androidx fragment. I want to ask is there any way to restore state of fragment in middle of language change configuration. For example I have 1 activity and 4 fragments.

Activity

1st Fragment > 2 Fragment > 3 Fragment > 4 Fragment

Like this I have fragments in single activity. In 1st Fragment I am calling 3 api call through retrofit. I have some callbacks in each fragments. In 1st Fragment I have 2 callback which execute api calls.

Also I have logic to jump directly in 3 Fragment with calling each fragment to go and showing loading spinner to user. Now main scenario starts.

when I am in 3rd Fragment. I change my device language and my 1st fragment callback not called and the result is blank screen. So I am thinking to store my fragment state and restore when created the activity may be that would help me.

Please I checked this answer. I read somewhere Is to use viewmodel to save state of fragment. Using koin for Dependency Injection for my viewmodel. I need latest answer and how to store whole fragment instance?. Please don't add link of google doc. I already tried from there and it didn't work for me. Thanks

activity.kt

    class StepsBaseActivity : : AppCompatActivity() {
    
     internal lateinit var binding: ctivityLayoutBinding
     private val viewModel: ActivityViewModel by inject() 
     var fragment: Fragment? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setupViewModel()
            binding = ActivityLayoutBinding.inflate(layoutInflater)
            setContentView(binding.root)
           loadScreensList()
        }
    
         private fun setupViewModel() {
            viewModel.infoLiveData.observe(this, { info ->
                    info?.let{
                      switchFragment(info)
                    }
                }
            })
        }

   private fun loadScreensList() {
      viewModel.setupScreenSteps()
  }
    
   private fun switchFragment(data: FragmentStepData, arguments: Bundle? = null) {
        fragment = supportFragmentManager.findFragmentByTag(data.tag)
        if (fragment == null) {
            fragment = getFragmentForScreen(data)
            if (fragment != null) {
                arguments?.let {
                    fragment?.arguments = arguments
                }
                supportFragmentManager
                    .beginTransaction()
                    .replace(
                        R.id.fragment_container, fragment!!,
                        data.tag
                    )
                    .addToBackStack(null)
                    .commitAllowingStateLoss()
            }
        }
    }
    
    
    fun getFragmentForScreen(data: FragmentStepData): FragmentBase{
        return when (getScreen(data.screen)) {
            Screen.FRAGMENT_ONE -> FragmentOne()
                ..... // till 4
                null -> null
        }
    }
   }

ActivityViewModel.kt

class ActivityViewModel : ViewModel {

   val infoLiveData = MutableLiveData<StepsInfo>()

   fun setupScreenSteps() {
     viewModelScope.launch {
        val list = mutableListOf<StepsInfo>()
        list.add(StepsInfo(Screen.FRAGMENT_ONE , "fragment_one"))
        list.add(StepsInfo(Screen.FRAGMENT_TWO , "fragment_two"))
        list.add(StepsInfo(Screen.FRAGMENT_THREE , "fragment_three"))
        list.add(StepsInfo(Screen.FRAGMENT_FOUR , "fragment_four"))

        infoLiveData.postValue(list)
     }
   }
  fun fetchFirstFragmentApiCall(){ 
   // Through retrfoit
  }
  // All fragment api call
}

StepsInfo.kt

data class StepsInfo(val screen: Screen, val tag: String)

Screen.kt

enum class Screen{
   FRAGMENT_ONE,
   FRAGMENT_TWO,
   FRAGMENT_THREE,
   FRAGMENT_FOUR
}
Kotlin Learner
  • 3,995
  • 6
  • 47
  • 127
  • 1
    Fragments are already saved automatically across configuration changes (you've set a tag, which means `findFragmentByTag()` is going to let you retrieve that same instance). All of the [recommended APIs for communicating with fragments](https://developer.android.com/guide/fragments/communicate) also survive configuration changes. – ianhanniballake Jan 23 '22 at 23:47
  • @ianhanniballake can you please give me example how can I achieved this – Kotlin Learner Jan 24 '22 at 04:42
  • From the code you've shown, all of the fragments you've added and the entire back stack you've built will automatically be saved and restored (if you add logging in `onCreate()`, you'll note them all get recreated). You haven't shown anything that wouldn't be restored automatically. Please add the actual code you've having problems with. – ianhanniballake Jan 24 '22 at 04:52
  • @ianhanniballake `switchFragment()` function is calling on `oncreate`. I don't know how to restore fragment and I don't have any code to be honest. Can you please guide me how to do that ? – Kotlin Learner Jan 24 '22 at 05:18
  • Are you calling that method only if `savedInstanceState == null` like [the docs specifically point out](https://developer.android.com/guide/fragments/create#add-programmatic)? Please include your `onCreate()` code. – ianhanniballake Jan 24 '22 at 05:26
  • @ianhanniballake I update my activity code please have a look. If you need more code about view model please let me know. Thanks – Kotlin Learner Jan 24 '22 at 05:53
  • All the code you included just calls into a ViewModel which you haven't included. Yes, of course you need to include your ViewModel code. – ianhanniballake Jan 24 '22 at 06:08
  • @ianhanniballake I added my view model code and class which are I am using. Please have a look – Kotlin Learner Jan 24 '22 at 06:26
  • @ianhanniballake other functions api call through [callback](https://stackoverflow.com/a/45954099/11560810) – Kotlin Learner Jan 24 '22 at 06:40
  • Use LiveData or StateFlow in your ViewModel, they hold state even on configuration changes. – OneDev Jan 24 '22 at 07:03

0 Answers0