https://kotlinlang.org logo
Title
j

Jan

05/24/2023, 8:14 AM
Hi, I was wondering if I have to unsubscribe to lifecycle in my component If I do the following:
class SomeComponent(
    componentContext: ComponentContext
) : ComponentContext by componentContext {
    init {
        lifecycle.subscribe(
            object : Lifecycle.Callbacks {
                override fun onCreate() {
                }
            }
        )
    }
}
Or if I have to to it like this:
class SomeComponent(
    componentContext: ComponentContext
) : ComponentContext by componentContext {
    private val lifeCycleObserver: Lifecycle.Callbacks = object : Lifecycle.Callbacks {
        // listen to onCreate, onStart, onPause, onResume, onStop, onDestroy
    }

    init {
        lifecycle.doOnCreate {
            lifecycle.subscribe(lifeCycleObserver)
        }

        lifecycle.doOnDestroy {
            lifecycle.unsubscribe(lifeCycleObserver)
        }
    }
}
a

Arkadii Ivanov

05/24/2023, 8:48 AM
No need to unsubscribe in this particular case, since the callback is registered in the scope of the component itself.
Also, you can just write
lifecycle.doOnCreate {}
instead of the anonymous class.
j

Jan

05/24/2023, 8:54 AM
yes, I know. I just want to build a base component with all the hooks which I can overwrite if needed
a

Arkadii Ivanov

05/24/2023, 8:57 AM
In this case, your (base) component may implement Lifecycle.Callbacks interface (no need to override any methods), and then just
lifecycle.subscribe(this)
.
j

Jan

05/24/2023, 8:57 AM
yes, thats what I came up with as well
abstract class AComponent(
    componentContext: ComponentContext
) : Lifecycle.Callbacks, ComponentContext by componentContext {
    init {
        lifecycle.subscribe(this)
    }

    override fun onCreate() {
    }

    override fun onDestroy() {
    }

    override fun onPause() {
    }

    override fun onResume() {
    }

    override fun onStart() {
    }

    override fun onStop() {
    }
}
image.png
a

Arkadii Ivanov

05/24/2023, 9:03 AM
That's actually a valid warning!
When you subscribe to the lifecycle in your base class, some callbacks may be called immediately (synchronously), and so your subclass will be called before its
init
section is called.
I wouldn't use the base class for this. Instead, I would implement
Lifecycle.Callbacks
interface where needed and override only required methods, and just call
lifecycle.subscribe(this)
as the last statement in the
init
section.
j

Jan

05/24/2023, 9:07 AM
ok, interesting.
a

Arkadii Ivanov

05/24/2023, 9:08 AM
If you really want those Android-style lifecycle callbacks. 😀
j

Jan

05/24/2023, 9:12 AM
I guess sometimes I need this. E.g.: • I have a composable with Scaffold, TopBar and Content • Content is a Component with a StackNavigation In order to update my title of the TopBar I pass a "onTitleChangeAction:(String)-Unit) to my ChildComponents within StackNavigation. This "action" is then called on each onStart so that the title is updated correctly
In you decompose-example the TopBar is included within in CounterComponent/CounterContent, but thats not what I want. Therefore I execute that action in "onStart" of my ChildComponent to let my parent component know that the title changed.
Hope you get what I try to achieve 😉
a

Arkadii Ivanov

05/24/2023, 9:25 AM
Sure! In this case I would just write
lifecycle.doOnStart { onTitleChangeAction("some title") }
.
j

Jan

05/24/2023, 9:30 AM
yes, maybe the delegation pattern is a better approach instead of class hieracy