【问题标题】:How to Bind/Provide Activity or Fragment with Hilt?如何使用 Hilt 绑定/提供 Activity 或 Fragment?
【发布时间】:2020-08-01 16:51:20
【问题描述】:

我正在尝试在 Android 应用程序上实现 Hilt,虽然它很容易实现并且与 Dagger 相比删除了很多样板代码,但我错过了一些东西,比如构建我自己的组件并自己确定它们的范围所以我会有自己的雇佣关系。

直截了当:示例:假设我有一个简单的应用程序,其中包含一个 RecyclerView、Adapter、Acitivity 和一个嵌套在我的 Adapter 中的回调,我将它传递给我的 Adapter 构造函数以检测点击或其他什么,我正在让我的活动实现回调,当然我想注入适配器。

class @Inject constructor (callBack: Callback): RecyclerView.Adapter...

当我让 Hilt 知道我想注入我的适配器时,我需要让 Hilt 知道如何提供所有适配器依赖项 - 回调。

在 Dagger 中,我只需将 Activity 绑定到我的一个模块中的回调即可实现此目的:

@Binds fun bindCallback(activity: MyActivity): Adapter.Callback

Dagger 知道如何绑定 Activity(或任何 Activity/Fragment),然后将其链接到该回调,但使用 Hilt 它不起作用。

我怎样才能做到这一点?如何使用 Hilt 提供或绑定 Activity 或 Fragment?

【问题讨论】:

    标签: android kotlin dependency-injection dagger-hilt


    【解决方案1】:

    解决方法很简单。

    所以几天前我回来查看我的问题只是发现仍然没有新的解决方案,所以我尝试了 Bartek 解决方案并无法使其工作,即使它确实有效,干净的 Hilt 代码变得太乱了,所以我做了一些调查并玩了一点,发现解决方案实际上非常简单。

    是这样的:

    应用:

    @HiltAndroidApp
    class MyApp: Application()
    

    Activity:(实现回调)

    @AndroidEntryPoint
    class MainActivity : AppCompatActivity(), SomeClass.Callback {
    
        @Inject
        lateinit var someClass: SomeClass
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)  
        }
    
        override fun onWhatEver() {
            // implement
        }
    }
    

    SomeClass:(带有内部回调)

    class SomeClass @Inject constructor(
        private val callback: Callback
    ) {
    
        fun activateCallback(){
            callback.onWhatEver()
        }
    
        interface Callback{
            fun onWhatEver()
        }
    }
    

    SomeModule:(将活动提供/绑定到回调)

    @Module
    @InstallIn(ActivityComponent::class)
    object SomeModule{
    
        @Provides
        fun provideCallback(activity: Activity) =
            activity as SomeClass.Callback
        
    }
    

    这就是我们所需要的。 我们无法使用 @Bind 将活动绑定到回调,因为它需要显式提供并强制转换为回调,以便应用可以构建。

    模块安装在 ActivityComponent 中,并且知道一个通​​用的 'activity',如果我们将其强制转换为回调,Hilt 是内容并且活动绑定到回调,并且 Hilt 将知道如何提供回调在具体的活动范围内。

    多个活动/片段

    应用:

    @HiltAndroidApp
    class MyApp: Application()
    

    图书活动:

    @AndroidEntryPoint
    class BooksActivity : AppCompatActivity(), BooksAdapter.Callback{
    
            @Inject
            lateinit var adapter: BooksAdapter
    
            ...
    
            override fun onItemClicked(book: Book) {...}
        }
    }
    

    作者活动:

    @AndroidEntryPoint
    class AuthorsActivity : AppCompatActivity(), AuthorsAdapter.Callback{
    
        @Inject
        lateinit var adapter: AuthorsAdapter
    
        ...
    
        override fun onItemClicked(author: Author) {...}
    }
    

    图书适配器

    class BooksAdapter @Inject constructor (
        val callback: Callback
    ) ... {
    
        ...
    
        interface Callback{
            fun onItemClicked(book: Book)
        }
    }
    

    作者适配器

    class AuthorsAdapter @Inject constructor (
        val callback: Callback
    ) ... {
    
        ...
    
        interface Callback{
            fun onItemClicked(auhtor: Auhtor)
        }
    }
    

    作者模块

    @Module
    @InstallIn(ActivityComponent::class)
    object AuthorsModule {
        @Provides
        fun provideCallback(activity: Activity) =
            activity as AuthorsAdapter.Callback
    }
    

    书籍模块

    @Module
    @InstallIn(ActivityComponent::class)
    object BooksModule {
        @Provides
        fun provideCallback(activity: Activity) =
            activity as BooksAdapter.Callback
    }
    

    模块可以毫无问题地连接到一个模块,只需更改函数的名称即可。

    这当然适用于更多活动和/或多个片段......适用于所有逻辑案例。

    【讨论】:

    • 很酷,您为自己的情况解决了这个问题!恭喜!我的两分钱:我会采用更复杂但更明确的依赖组件结构而不是运行时,一周中的每一天都深埋在Module 结构中的未经检查的演员表。在任何拥有多个Activity 的项目中,您的方法只是自找麻烦。
    • 由于整个有价值的讨论已被删除,因此总结如下:我的意见是这是一个非常糟糕的选择。当然,它 ISN'T 就像作者在(现已删除)评论中建议的那样:“解决方案 [...] 适合所有情况”。小心使用。
    【解决方案2】:

    Hilt 可以提供通用Activity(和Fragment)的实例作为ActivityComponent(分别是FragmentComponent)中的依赖项。它只是无法提供您特定 MyActivity 的实例。

    您仍然可以create your own Component in Hilt。您只需要自己管理component 实例。将MyActivity 添加为组件构建器的种子数据,您应该能够@Bind 您的Callback 没有问题。

    【讨论】:

    • 感谢您的回答,虽然这是一个很好的答案,但我正在等待一个更好的解决方案,希望更干净,如果没有,我会接受您的回答。 (如果你能提供一个代码示例也很好)
    • 创建自定义组件的示例?
    • 嗨@BartekLipinski,你能添加一个自定义组件的例子,它有助于将指定的活动注入到一个类中吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多