我们在应用程序中使用Dagger2。我正在尝试做一个房间数据库,我正在编写存储库代码,但是我想为类注入应用程序上下文和DAO。
我有一种感觉,你只能在碎片,活动,服务,应用等中注射匕首。
我现在拥有的是:
class DownloadsDataRepositoryImpl : IDownloadsDataRepository, HasAndroidInjector {
@Inject
lateinit var androidInjector : DispatchingAndroidInjector<Any>
@Inject
lateinit var downloadsDao: DownloadsDao
override fun androidInjector(): AndroidInjector<Any> = androidInjector
init {
androidInjector()
}
}但我肯定这行不通。有办法吗?
发布于 2020-03-31 19:12:15
如前所述,匕首-android只是一个工具,用来帮助注入无法控制其创建的特定框架类。
正确的方法是使用简单的施工注射。
为了更直接地了解应该如何在@Component上公开它,我需要更多的代码,特别是关于您的活动/片段的代码,但是下面是一个粗略的示例(我没有测试这个示例,如果有一些小错误,您可以在编译器错误消息之后修复它们):
首先,您将有一些公开您的DAO的对象。可能是房间?
@Entity(tableName = "download_table")
data class DownloadEntity(
@PrimaryKey
val key: String
)
@Dao
interface DownloadsDao {
@Query("SELECT * FROM download_table")
fun load(): List<DownloadEntity>
}
@Database(
entities = [DownloadEntity::class], version = 1
)
abstract class DownloadRoomDatabase : RoomDatabase() {
abstract val downloadsDao: DownloadsDao
}现在,我们将创建一个使用@Inject注释构建的粗糙存储库。匕首会帮我们建造这个物体的。请注意,我没有使用匕首-android:
interface IDownloadsDataRepository
class DownloadsDataRepositoryImpl @Inject constructor(
val downloadsDao: DownloadsDao
) : IDownloadsDataRepository如何将其公开给您的活动/片段/服务需要更多关于您的实现的细节。例如,如果它在ViewModel或使用@Inject注释的Presenter中,或者您正在直接访问您的活动,则会产生不同的实现。如果没有更多的详细信息,我将假设您直接访问您的活动上的存储库:
class DownloadActivity : FragmentActivity() {
@Inject
lateinit val repo: IDownloadsDataRepository
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DaggerDownloadComponent.factory().create(this).inject(this)
}
}现在我们需要指示Dagger如何:
为此,我们需要一个模块
@Module
abstract class RepositoryModule {
//We will bind our actual implementation to the IDownloadsDataRepository
@Binds
abstract fun bindRepo(repo: DownloadsDataRepositoryImpl): IDownloadsDataRepository
@Module
companion object {
//We need the database to get access to the DAO
@Provides
@JvmStatic
fun provideDataBase(context: Context): DownloadRoomDatabase =
Room.databaseBuilder(
context,
DownloadRoomDatabase::class.java,
"download_database.db"
).build()
//With the database, we can provide the DAO:
@Provides
@JvmStatic
fun provideDao(db: DownloadRoomDatabase): DownloadsDao = db.downloadsDao
}
}这样,我们就可以完成拼图的最后一部分,创建@Component。
@Component(
modules = [
RepositoryModule::class
]
)
interface DownloadComponent {
fun inject(activity: DownloadActivity)
@Component.Factory
interface Factory {
fun create(context: Context): DownloadComponent
}
}请注意,我没有使用任何dagger-android代码,我不认为它很有用,而且会造成不必要的混乱。坚持使用基本的dagger2结构,您就可以了。您只需了解这些构造是如何工作的,就可以实现99.9%的应用程序:
@Module、@Component和@Subcomponent
发布于 2020-03-31 17:16:52
不确定如何实现匕首,但下面是一个示例,您可以为非活动类提供上下文。
假设您有AppModule类,那么您可以在那里添加provideContext()方法:
@Module
class AppModule(app: App) {
private var application: Application = app
@Provides
fun provideContext(): Context {
return application
}
}下面是用Kotlin编写的非活动类:
类Utils @inject构造函数(私有val上下文: Context) { ..}
就这样,重建j
发布于 2020-04-01 01:00:16
我有一种感觉,你只能在碎片,活动,服务,应用等中注射匕首。
在Dagger-Android2.20之前,但在2.20+之后,你的假设是正确的。
现在您可以为任何类创建一个@ContributesAndroidInjector,这将为添加了@ContributesAndroidInjector的T生成一个@ContributesAndroidInjector。
这意味着有一个多绑定,允许您为T获取一个T,这就是HasAndroidInjector为您所做的。
因此,以下内容在另一种情况下适用于我(针对工作经理中的成员注射工人,而不是创建多绑定和工厂):
@Keep
class SyncWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
init {
val injector = context.applicationContext as HasAndroidInjector
injector.androidInjector().inject(this)
}
@Inject
lateinit var apiService: ApiService和
@ContributesAndroidInjector
abstract fun syncWorker(): SyncWorker然而,在您的特殊情况下,这是不需要的。
Dagger-Android是用于使用自动生成的子组件的成员注入类,通常只有在注入类型位于不同模块内时才需要这些子组件,因此不能将fun inject(T t)直接添加到AppComponent中,否则看不到AppComponent。
在您的例子中,简单的构造函数注入就足够了,因为您拥有自己的类。
@Singleton
class DownloadsDataRepositoryImpl @Inject constructor(
private val downloadsDao: DownloadsDao
): IDownloadsDataRepository {},您可以通过模块绑定
@Module
abstract class DownloadsModule {
@Binds
abstract fun dataRepository(impl: DownloadsDataRepositoryImpl): IDownloadsDataRepository
}否则,您只需在Application.onCreate()中创建组件实例即可。
@Component(modules = [DownloadsModule::class])
@Singleton
interface AppComponent {
fun dataRepository(): DownloadsDataRepository
@Component.Factory
interface Factory {
fun create(@BindsInstance appContext: Context): AppComponent
}
}和
class CustomApplication: Application() {
lateinit var component: AppComponent
private set
override fun onCreate() {
super.onCreate()
component = DaggerAppComponent.factory().create(this)
}
}然后你就可以得到它
val component = (context.applicationContext as CustomApplication).component尽管从技术上讲,您可以创建一个扩展函数。
val Context.appComponent: AppComponent
get() = (applicationContext as CustomApplication).component
val component = context.appComponenthttps://stackoverflow.com/questions/60955695
复制相似问题