android - 使用 Dagger 2 自动注入(inject) Activity 的问题

标签 android dependency-injection kotlin dagger-2

我对 Daggers 依赖注入(inject)还是很陌生。我正在开发一个使用 Dagger 2 和 Kotlin 的新应用程序。我从一个用于构建的基本入门应用程序开始。在 App.kt 中,每个 Activity 都被自动注入(inject),到目前为止这非常酷。但是,我现在在实现 Facebook 和 Google 社交登录时遇到了问题。

当应用程序尝试启动 Facebook 或 Google 登录 Activity 时,我收到错误消息:

"No injector factory bound for Class<external.activities.classNameHere>"

我不能@Provides 那些外部类,因为它们没有实现@Module 注释。

我的临时解决方案是在自动注入(inject)之前检查正在注入(inject)的 Activity ,并跳过那些外部类。不过这似乎有点奇怪,我想知道是否有更好的解决方案,或者我是否遗漏了什么。我可以看到这个 if 语句随着时间的推移变得很长。

 registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks() {
        override fun onActivityCreated(p0: Activity?, p1: Bundle?) {
            p0?.let {
                if (p0 is FacebookActivity || p0 is CustomTabMainActivity || p0 is CustomTabActivity ) {
                    Log.d("KSULog", "App.kt is not injecting activity " + p0.toString())
                }
                else {
                    AndroidInjection.inject(p0)
                }

            }
        }
    })
}

感谢您的关注。

最佳答案

实现这个的方法很简单。 如果您查看 Google Samples,您将有一个明确的方向。喜欢GitHubBrowserSample

因此,您将像这样创建一个 interface Injectable,基本上是一个标记接口(interface)。

/**
 * Marks an activity / fragment injectable.
 */
interface Injectable

每个 Activity 或 fragment 都将实现此接口(interface),例如(在 Kotlin 中)

open class BaseActivity : AppCompatActivity(),Injectable {

@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
lateinit var baseActivityViewModel: BaseActivityViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    AndroidInjection.inject(this)
    baseActivityViewModel = ViewModelProviders.of(this, viewModelFactory)
            .get(BaseActivityViewModel::class.java)
}

重要的几行是:

打开类 BaseActivity : AppCompatActivity(),Injectable

AndroidInjection.inject(this)

创建一个Activity模块贡献Activity对象

/**
 * Module to contribute all the activities.
 */
@Module
abstract class ActivityModule {

    @ContributesAndroidInjector
    internal abstract fun contributeSplashActivity(): SplashActivity

}

最后是 DaggerInjector 以启用注入(inject)

/**
 * Helper to inject all the activities and fragments that are marked Injectable.
 */

object DaggerInjector {

    fun injectAll(application: TurtleApp) {
        DaggerAppComponent.builder()
                .application(application)
                .build().inject(application)
        application
                .registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
                    override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                        injectComponents(activity)
                    }

                    override fun onActivityStarted(activity: Activity) {

                    }

                    override fun onActivityResumed(activity: Activity) {

                    }

                    override fun onActivityPaused(activity: Activity) {

                    }

                    override fun onActivityStopped(activity: Activity) {

                    }

                    override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {

                    }

                    override fun onActivityDestroyed(activity: Activity) {

                    }
                })
    }

    private fun injectComponents(activity: Activity) {
        if (activity is Injectable) {
            AndroidInjection.inject(activity)
        }
//        (activity as? FragmentActivity)?.supportFragmentManager?.registerFragmentLifecycleCallbacks(
//                object : FragmentManager.FragmentLifecycleCallbacks() {
//                    override fun onFragmentCreated(fm: FragmentManager?, f: Fragment?,
//                                                   savedInstanceState: Bundle?) {
//                        if (f is Injectable) {
//                            AndroidSupportInjection.inject(f)
//                        }
//                    }
//                }, true)
    }
}

取消注释代码以启用 Fragment 注入(inject)。

关于android - 使用 Dagger 2 自动注入(inject) Activity 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51489023/

相关文章:

android - 如何使用 Genymotion 在 PC 上启动 Android 应用程序?

android - 将 ActionBarSherlock 添加到我的项目后,我的 R.java 文件消失了

android - 游标索引越界 “index 0 requested: with size 0”

c# - 在 ASP.NET Core 依赖注入(inject)中使用非泛型实现注册泛型接口(interface)

spring - Autowire Spring bean 实现两个接口(interface)

dependency-injection - NUnit 集成测试和依赖注入(inject)

java - void 函数/属性调用在哪里执行?

kotlin - 如何从 kotlin 引用 bool java 类?

android - 如何使用 AndEngine 确定在屏幕上画线的位置

generics - Star 投影集合中的特定 KClass