onActivityCreated is deprecated, how to properly use LifecycleObserver?
AndroidAndroid FragmentsAndroid ActivityAndroid LifecycleAndroid Problem Overview
Google deprecate fragment’s onActivityCreated() on Android and recommend to use LifeCycleObserver:
To get a callback specifically when a Fragment activity's
* {@link Activity#onCreate(Bundle)} is called, register a
* {@link androidx.lifecycle.LifecycleObserver} on the Activity's
* {@link Lifecycle} in {@link #onAttach(Context)}, removing it when it receives the
* {@link Lifecycle.State#CREATED} callback.
So I try to make it in recommended way, but only state I can observe in Logcat is just State: INITIALIZED.
private lateinit var lifecycleObserver: LifecycleObserver
override fun onAttach(context: Context) {
super.onAttach(context)
hostActivity = context as HostActivity
lifecycleObserver = object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
Logger.tag("SOME-TAG")d("State: ${lifecycle.currentState}")
if(lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)) {
Logger.tag("SOME-TAG").d("CREATED")
hostActivity.lifecycle.removeObserver(lifecycleObserver)
}
}
}
hostActivity.lifecycle.addObserver(lifecycleObserver)
}
What is wrong in code above?
UPDATE 1: Looks like I forgot to use hostActivity.lifecycle.currentState and checked fragment's lifecycle instead of Activities lifecycle.
UPDATE 2: Suggested by Google approach not worked for 1 Host activity and 2 fragments when you click back button from one to another, cause onAttach never called, but onActivityCreated called.
Android Solutions
Solution 1 - Android
As per the changelog here
> The onActivityCreated()
method is now deprecated. Code touching the
> fragment's view should be done in onViewCreated()
(which is called
> immediately before onActivityCreated()
) and other initialization code
> should be in onCreate()
. To receive a callback specifically when the
> activity's onCreate()
is complete, a LifeCycleObserver
should be
> registered on the activity's Lifecycle in onAttach()
, and removed once
> the onCreate()
callback is received.
You can do something like this in your fragment class:
class MyFragment : Fragment(), LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreated() {
// ... Your Logic goes here ...
}
override fun onAttach(context: Context) {
super.onAttach(context)
activity?.lifecycle?.addObserver(this)
}
override fun onDetach() {
activity?.lifecycle?.removeObserver(this)
super.onDetach()
}
}
Solution 2 - Android
I did it in next way:
class MyActivityObserver(
private val update: () -> Unit
) : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
owner.lifecycle.removeObserver(this)
update()
}
}
and use it in fragments onAttach (or another lifecycle method) like:
myActivity.lifecycle.addObserver(MyActivityObserver {
myOnActivityCreated()
})
Solution 3 - Android
You can consider the Lifecycle.State as the nodes in a graph and Lifecycle.Event as the edges between these nodes.
So you will never reached the State.Created on your ON_CREATE function.
Solution
class YourFragment : Fragment(), LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onCreated(){
Log.i("tag","reached the State.Created")
}
override fun onAttach(context: Context) {
super.onAttach(context)
lifecycle.addObserver(this)
}
override fun onDetach() {
super.onDetach()
lifecycle.removeObserver(this)
}
}
For more details
https://developer.android.com/topic/libraries/architecture/lifecycle#lc
Solution 4 - Android
The best way to solve the issue is to use lifecycleScope
which is present in the activity lifecycle. Below is the code snippet
override fun onAttach(context: Context) {
super.onAttach(context)
activity?.lifecycleScope?.launchWhenCreated {
setupActionbar()
}
}
How does it work? launchWhenXxx
runs the launch block when it automatically reaches the specified state(in this case it is Created) and if the lifecycle goes to the destroyed state it cancels the launched coroutine automatically. Internally lifecycleScope
uses Dispatchers.Main.immediate
and hence there is no penalty of thread switching
Pros of this approach are following:
- You don't have to manually maintain registering and deregistering of the observer
- No need to overwrite two lifecycle methods
You have to latest activity and fragment dependencies to use lifecycleScope attached to the lifecycle