Hilt注入在Leanback Presenter中

5

我对 Hilt 注入还比较新,刚开始将整个项目迁移到 DI。

它在几乎所有地方都能工作,但当涉及到 leanback presenter 时,我遇到了一个问题。我不知道这是否与 leanback 有关,还是只是 Hilt 的问题。

class LiveShowCardPresenter constructor(context: Context, listener: ShowCardViewListener, val hasVariableWidth: Boolean = false) : ShowCardPresenter(context, listener) {
    override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
        val viewholder = ViewHolder(LiveShowCardView(context, hasVariableWidth))
        viewholder.prepareViewHolderForeground(context, settings.isATV)
        return viewholder
    }
...
}

abstract class ShowCardPresenter constructor(val context: Context, var listener: ShowCardViewListener?) : Presenter() {
    @Inject lateinit var detailsRepository: DetailsRepository
    @Inject lateinit var settings: BackendSettings
... }

@Singleton
class BackendSettings @Inject constructor(@ApplicationContext val context: Context) {
    val isATV = true // TODO

以下错误发生了。
    kotlin.UninitializedPropertyAccessException: lateinit property settings has not been initialized
    at ch.netplus.tv.ui.presenters.ShowCardPresenter.getSettings(ShowCardPresenter.kt:43)
    at ch.netplus.tv.ui.presenters.LiveShowCardPresenter.onCreateViewHolder(LiveShowCardPresenter.kt:23)

这意味着当调用settings.isATV时会崩溃,因为此时“settings”变量尚未初始化。我该怎么做才能及时完成注入?

谢谢!


尝试将 val isATV = true 更改为 val isATV get() = truefun getIsATV(): Boolean { return true} - ltp
3个回答

1

您需要在BackendSettings中设置注入方法

例如:

class BackendSettings @Inject constructor() {

}

我添加了我的BackendSettings定义,它与您的建议非常相似。 - Hrk

1

好的,我将逐步解释您的代码:

您的LiveShowCardPresenter类应按以下方式更改:

class LiveShowCardPresenter @Inject constructor(
    @ApplicationContext context: Context,
    listener: ShowCardViewListener
) : ShowCardPresenter(context, listener) {

    var hasVariableWidth = false

    //your codes ...

}

可以看到,在构造函数之前添加了@Inject,同时在context之前添加了@ApplicationContext,以通过Hilt提供上下文。此外,hasVariableWidth是在构造函数之外设置的,如果您不喜欢,可以将其放在构造函数内并通过模块和@Provide注释提供它。现在我们应该提供showCardViewListener。由于我无法访问您的代码,因此我以简单的方式提供它。
 @Module
@InstallIn(SingletonComponent::class)
abstract class ShowCardListenerModule {
    @Binds
    @Singleton
    abstract fun bindShowCardViewListener(showCardViewListenerImpl: ShowCardViewListenerImpl) : ShowCardViewListener
}

ShowCardPresenter类没有变化。最后,您的BackendSettings类更改如下:

 @Singleton
class BackendSettings @Inject constructor() {
    val isATV = true
    //your codes ...
}

因为不需要,所以添加了@Inject并删除了@Singleton。我运行了上述代码,没有任何问题。


1

如何将依赖项注入LiveShowCardPresenter

由于您的抽象类(ShowCardPresenter)执行字段注入,因此在创建LiveShowCardPresenter时需要注入这些字段。为了执行这些注入,您还需要注入LiveShowCardPresenter。因此,以下是它的实现方式:

class LiveShowCardPresenter @Inject constructor(context: Context) : ShowCardPresenter(context) {
    var hasVariableWidth: Boolean = false

    override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
        val viewholder = ViewHolder(LiveShowCardView(context, hasVariableWidth))
        viewholder.prepareViewHolderForeground(context, settings.isATV)
        return viewholder
    }
    ...
}

abstract class ShowCardPresenter constructor(val context: Context) : Presenter() {
    var listener: ShowCardViewListener? = null

    @Inject lateinit var detailsRepository: DetailsRepository
    @Inject lateinit var settings: BackendSettings
... }

YourFragment.kt

@AndroidEntryPoint
class YourFragment: BrowseFragment() {
    @Inject
    lateinit var liveShowCardPresenterProvider: Provider<LiveShowCardPresenter>

    ...
    private void setupUIElements() {
        ...
        //new header
        setHeaderPresenterSelector(object : PresenterSelector() {
            override fun getPresenter(o: Any): Presenter {
                // Everytime when [liveShowCardPresenterProvider.get()] is called - new instance will be created
                val presenter = liveShowCardPresenterProvider.get().apply {
                    // You can set your parameters here
                    // hasVariableWidth = true
                    // listener = yourCustomListener
                }
                return presenter;
            }
        });
    }
    ...

如果你的fragment只需要一个LiveShowCardPresenter实例,你可以在它上面执行字段注入而不需要使用Provider。或者,你可以在Fragment中注入所有依赖项并将它们传递给LiveShowCardPresenter构造函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接