52

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.

Sever
  • 2,063
  • 4
  • 30
  • 51
  • Did you find a solution for the back issue? I have the same issue with the solution suggested by google. Wonder if I misunderstood what they said and actually updating the toolbar should not be happening in there and it should be tied to a fragment lifecycle instead. – Alex Jan 07 '22 at 20:33

4 Answers4

41

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()
    }
}
Top-Master
  • 5,262
  • 5
  • 23
  • 45
Embydextrous
  • 1,470
  • 1
  • 11
  • 20
  • 3
    Unlike normal `onActivityCreated()` that is called after `onViewCreated()`, the `onCreated()` method is called before `onCreateView()` – Misagh Emamverdi Jul 17 '21 at 16:23
  • This solution is deprecated. I add a current solution. – S. Gissel Feb 10 '22 at 13:47
  • d= (◕‿↼ ) Too bad! The `@OnLifecycleEvent` notation is deprecated nowadays as well, and docs suggest to use `DefaultLifecycleObserver` or `LifecycleEventObserver` instead. – Top-Master May 05 '22 at 16:58
  • 1
    (Someone tell Google to deside once forever, and not just write whatever, without any standard.) – Top-Master May 05 '22 at 17:01
13

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()
})
Sever
  • 2,063
  • 4
  • 30
  • 51
  • The "`.removeObserver(this)`" part is strange; always **only** remove Listeners and/or Observers in "`Fragment::onDetach`" callback, unless there is a special need to do otherwise. – Top-Master May 05 '22 at 18:26
  • @Top-Master What is strange? You add observer and you delete observer as you dont need it anymore. Why wait for detach in that case? OnCreate should be called only 1 time. – Sever May 14 '22 at 12:12
  • Putting `.removeObserver(this)` in `onCreate()` is confusing, as future readers may need to listen for far more events. – Top-Master May 14 '22 at 13:53
9

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

oaosj
  • 91
  • 2
5

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:

  1. You don't have to manually maintain registering and deregistering of the observer
  2. No need to overwrite two lifecycle methods

You have to latest activity and fragment dependencies to use lifecycleScope attached to the lifecycle

AndroidEngineX
  • 640
  • 6
  • 17