【问题标题】:Dagger 2 provisioning via Modules vs Inject constructorDagger 2 通过 Modules 与 Inject 构造函数进行配置
【发布时间】:2020-01-21 14:31:22
【问题描述】:

我正在尝试将 dagger-android 添加到 Kotlin 项目中,但在需要创建模块以及仅声明 Inject 构造函数就足够时感到困惑。

假设有如下依赖图:

Activity
    -> ViewModel
        -> Repository
            -> Webservice
            -> Dao
                -> Database
                    -> Application

为了为Activity 提供ViewModel,我们为Activity 和ViewModel 工厂创建各自的模块,然后像这样在Activity 中手动创建ViewModel:

@Module
abstract class ActivityModule {
    @ContributesAndroidInjector
    abstract fun mainActivity(): MainActivity
}

// Skiping ViewModelKey and ViewModelFactory code for brevity
@Module
abstract class ViewModelModule {
    @Binds
    internal abstract fun bindViewModelFactory(
        factory: ViewModelFactory
    ): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel::class)
    internal abstract fun mainViewModel(viewModel: MainViewModel): ViewModel
}

class MainActivity : DaggerAppCompatActivity() {
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        viewModel = ViewModelProviders.of(this, viewModelFactory)
            .get(HomeViewModel::class.java)
    }
}

要为ViewModel 提供Repository,我们只需像这样声明@Inject constructor

class MainViewModel @Inject constructor(private val repository: Repository): ViewModel() {}

为了为 Repository 提供 WebserviceDao 以及为 Dao 提供 Database,我们创建了相应的模块,如下所示:

@Module
class NetworkModule {
    @Provides
    @Singleton
    fun provideWebservice() = Webservice.create()
}

interface Webservice {
    ...
    companion object Factory {
        fun create(): Webservice {
            ...
            return retrofit
        }
    }
}


@Module
class DataModule {
    @Provides
    @Singleton
    fun provideApplicationDatabase(app: Application) =
        AppDatabase.getDatabase(app)

    @Provides
    @Singleton
    fun provideUserDao(db: AppDatabase) = db.userDao()
}

@Database(...)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao

    companion object {
        fun getDatabase(context: Context): AppDatabase {
            ...
            return instance
        }
    }
}

Application 是通过 AppComponent 和 Application 类中的某种魔法为 Dabatabase 提供的

@Singleton
@Component(modules = [
    AndroidSupportInjectionModule::class,
    NetworkModule::class,
    DataModule::class,
    ViewModelModule::class,
    ActivityModule::class
])
interface AppComponent: AndroidInjector<App> {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun create(application: Application): Builder
        fun build(): AppComponent
    }
}

class App : DaggerApplication() {
    override fun applicationInjector(): AndroidInjector<out DaggerApplication> =
        DaggerAppComponent.builder().create(this).build()
}

问题是

  1. 数据库如何获取应用程序实例?是 AndroidSupportInjectionModule 发挥了作用吗?
  2. 为什么我们需要为 Web 服务和数据库创建模块而不是存储库? 是否可以对 Webservice 接口和 Database 类本身进行注释以跳过为它们创建单独的 dagger 模块?

【问题讨论】:

  • 第 1 个问题与 Dagger 工作有关。您可以在初始化代码(构造函数?)中抛出一些异常并查看调用堆栈。顺便说一句,你使用 Dagger 2 吗(版本 2 在查找依赖项的方式上有所不同)?

标签: android kotlin dagger-2


【解决方案1】:

问题1 Database如何获取Application实例?是 AndroidSupportInjectionModule 有魔法吗?

答案: 不,这不是 AndroidSupportInjectionModule 的工作。 AndroidSupportInjectionModule 包含在 Dagger Android Support 中,它有助于

“配置绑定以确保 dagger.android 和 dagger.android.support 框架类的可用性。” Found Here

所以,基本上你只是在创建 Dagger Builder 时传递应用程序上下文,你现在只需从应用程序类传递它一旦你在主组件中得到它,你的所有模块中都有应用程序上下文,当我们需要上下文时初始化房间数据库。

问题 2 为什么我们需要为 Web 服务和数据库创建模块而不是存储库?是否可以对 Webservice 接口和 Database 类本身进行注释以跳过为它们创建单独的 dagger 模块?

答案: 首先,总是尽量实现构造函数注入。 Modules 的总体思路是“如果我们不拥有这个类,我们就不能 @annotate 它的构造函数,所以我们制作 Modules 来提供它们的实现”。如果我们想注入接口,我们可以通过它的构造函数注入通过它的实现类来实现它。
所以我们不拥有 WebService 和数据库的初始化,这就是我们创建它们的模块并提供它们的原因,以便我们可以在我们的存储库中获取它们的实例。我们拥有我们的存储库类,因此我们可以通过构造函数注入来注入它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    • 2017-12-24
    • 1970-01-01
    • 2015-11-11
    • 2011-05-13
    • 2019-02-23
    相关资源
    最近更新 更多