<@UHAJKUSTU> I am facing this issue where it says ...
# decompose
v
> @Arkadii Ivanov I am facing this issue where it says > java.lang.NullPointerException: Parameter specified as non-null is null: Code in thread 🧵
Lets say I have this abstract class
Copy code
abstract class FeedComponent(
    componentContext: ComponentContext,
) : BaseComponent(componentContext) {

    private val pagesNavigation = PagesNavigation<FeedPagesConfig>()
    
    internal val pages: List<FeedPagesConfig> = listOf(
        FeedPagesConfig.Trending,
        FeedPagesConfig.Latest
    )


    internal val childPages = childPages(
        source = pagesNavigation,
        initialPages = { Pages(pages, 0) },
        serializer = FeedPagesConfig.serializer(),
        childFactory = ::createChild
    )

    internal abstract fun createComponent(
        config: FeedPagesConfig,
        componentContext: ComponentContext
    ): FeedPageComponent

    private fun createChild(
        config: FeedPagesConfig,
        componentContext: ComponentContext
    ): FeedPages {
        val component = createComponent(config, componentContext)
        return when(config) {
            FeedPagesConfig.Trending -> FeedPages.Trending(component)
            FeedPagesConfig.Latest -> FeedPages.Latest(component)
        }
    }


    internal fun onPageSelected(index: Int) {
        pagesNavigation.select(index)
    }

}
And this is the child class
Copy code
internal class FeedTabComponent(
    componentContext: ComponentContext,
    private val onTabReselected: Flow<Unit>,
    val onNavEvent: (AppNavEvents) -> Unit
) : FeedComponent(componentContext) {

    override fun createComponent(
        config: FeedPagesConfig,
        componentContext: ComponentContext
    ) = FeedTabPageComponent(
        feedCategory = config.feedCategory,
        componentContext = componentContext,
        onTabReselected = onTabReselected,
        onNavEvent = onNavEvent
    )
}
This is the leaf component
Copy code
internal class FeedTabPageComponent (
    feedCategory: FeedCategory,
    componentContext: ComponentContext,
    val onTabReselected: Flow<Unit>,
    override val onNavEvent: (AppNavEvents) -> Unit
): FeedPageComponent(componentContext) {

    override val component = this

    override val feed = feedItemRepo.getFeedPaged(feedCategory).pagedData
        .mapLatest { it.map(FeedItemEntity::toDomain) }
        .cachedIn(componentScope)
        .safeCatch { setError(it) }
        .toStateFlow(componentScope, PagingData.empty())
}
Now i'm getting this error that > java.lang.NullPointerException: Parameter specified as non-null is null: method com.medial.app.ui.screens.screens.home.tabs.feed.pages.FeedTabPageComponent.init, parameter onTabReselected
But isnt it a constructor parameter and hence will always be initialized before childPages is created
a
I think in this case,
childStack
is initialised during
super
(FeedComponent) constructor invocation. This also calls
createChild
and
createComponent
functions. Since the
createComponent
is overriden, it gets called before the extending class is fully initialised.
v
@Arkadii Ivanov Can this be solved?
a
This is a general concern in Kotlin and Java - this is how things work. My usual advice is to avoid having base classes - prefer composition over inheritance. Another solution that is likely to help - get rid of all the
abstract
functions and use IoC instead - i.e. pass the factory to the
FeedComponent
via constructor. A short-term fix that may work - to make your
childStack
property
by lazy
. But I wouldn't recommend this.