Fragments destroyed / recreated with Jetpack's Android Navigation components Fragments destroyed / recreated with Jetpack's Android Navigation components android android

Fragments destroyed / recreated with Jetpack's Android Navigation components


Ian Lake from google replied me that we can store the view in a variable and instead of inflating a new layout, just return the instance of pre-stored view on onCreateView()

Source: https://twitter.com/ianhlake/status/1103522856535638016

Leakcanary may show this as leak but its false positive..


You can have a persistent view for your fragment through below implementation

BaseFragment

open class BaseFragment : Fragment(){        var hasInitializedRootView = false        private var rootView: View? = null        fun getPersistentView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?, layout: Int): View? {            if (rootView == null) {                // Inflate the layout for this fragment                rootView = inflater?.inflate(layout,container,false)            } else {                // Do not inflate the layout again.                // The returned View of onCreateView will be added into the fragment.                // However it is not allowed to be added twice even if the parent is same.                // So we must remove rootView from the existing parent view group                // (it will be added back).                (rootView?.getParent() as? ViewGroup)?.removeView(rootView)            }            return rootView        }    }

MainFragment

class MainFragment : BaseFragment() {    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {        return getPersistentView(inflater, container, savedInstanceState, R.layout.content_main)    }    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        if (!hasInitializedRootView) {            hasInitializedRootView = true            setListeners()            loadViews()        }    }}

Source


I tried like this, and it works for me.

  • Init ViewModel by navGraphViewModels (Live on Navigation scope)
  • Store any to-restore state in ViewModel
// fragment.ktprivate val vm by navGraphViewModels<VM>(R.id.nav_graph) { vmFactory }override fun onViewCreated(view: View, savedInstanceState: Bundle?) {    super.onViewCreated(view, savedInstanceState)    // Restore state    vm.state?.let {        (recycler.layoutManager as GridLayoutManager).onRestoreInstanceState(it)    }}override fun onPause() {    super.onPause()    // Store state    vm.state = (recycler.layoutManager as GridLayoutManager).onSaveInstanceState()}// vm.ktvar state:Parcelable? = null