My Fragment
:
class FirstFragment : Fragment() {
private lateinit var binding: FragmentFirstBinding
private lateinit var viewModelFactory: FirstViewModelFactory
private lateinit var viewModel: FirstViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_first, container, false)
viewModelFactory = FirstViewModelFactory(requireActivity().application, this.lifecycle) //<- Lifecycle object
viewModel = ViewModelProvider(this, viewModelFactory).get(FirstViewModel::class.java)
return binding.root
}
}
My ViewModel:
class FirstViewModel(application: Application, lifecycle: Lifecycle) : AndroidViewModel(application), LifecycleObserver {
init {
lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
private fun showOnStopMessage() {
Log.v("xxx", "onStop called!!")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
private fun showOnStartMessage() {
Log.v("xxx", "onStart called!!")
}
}
The above setup works well in no-configuration-change environment, showOnStopMessage()
gets called when app goes to the background, and showOnStartMessage()
gets called when the app is brought back to the foreground.
The problem is, when configuration-change happens (like rotating the screen), those functions are not being called any more.
Why this happens? How to detect and "survive" configuration-change? Thanks in advance.
As far as I understand, the problem is that your ViewModel is created only once (as it should be) and it only adds the lifecycle of the first fragment as a LifecycleObserver. When you rotate the screen, the same ViewModel is returned and it'll still try to react to the changes of the old Fragment, which won't happen.
I'd suggest not dealing with lifecycle inside the ViewModel at all (remove the related code from the Factory and from the ViewModel). Just call:
lifecycle.addObserver(viewModel)
right after the ViewModel is obtained, inside onCreateView.