如何通过击键绑定/提供活动或片段?

时间:2020-08-01 16:51:20

标签: android kotlin dependency-injection dagger-hilt

我正在尝试在Android App上实现Hilt,尽管与Dagger相比,它很容易实现并删除了许多样板代码,但有些东西我很想念,例如构建自己的组件并自行定义范围所以我会有自己的提包。

关键点:示例:假设我有一个简单的App,其中带有RecyclerView,Adapter,Acitivity和一个嵌套在我的Adapter中的回调,然后将其传递给我的Adapter构造函数以检测点击或其他情况,让我的活动实现该Callback,当然,我想注入适配器。

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

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

在Dagger中,我可以通过将Activity绑定到我的模块之一中的Callback上来实现这一目标:

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

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

我该如何实现?如何提供带有Hilt的活动或片段或将其绑定?

2 个答案:

答案 0 :(得分:6)

解决方案很简单。

所以前几天我回来看我的问题才发现仍然没有新的解决方案,所以我尝试了 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 将 Activity 绑定到回调,因为它需要明确提供并转换为回调,以便应用程序可以构建。

该模块安装在 ActivityComponent 中,并且知道一个通​​用的“活动”,如果我们将其强制转换为回调,则 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
}

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

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

答案 1 :(得分:1)

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

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