文章目录
- 一、前言
- 二、添加依赖
- 三、简单示例
- 四、作用域
- 五、自定义作用域
- 六、@Binds 和 @Provides
- 七、关于Dagger为什么在Android中要比Hilt复杂
- 八、inject(Activity act)的用法
- 十、参考链接
一、前言
Hilt是对Dagger的封装处理,这里对其进行下简单介绍。
二、添加依赖
    implementation 'com.google.dagger:dagger:2.41'
    kapt 'com.google.dagger:dagger-compiler:2.41'
三、简单示例
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) {
    fun printUserName(){
        localDataSource.printUserName()
    }
}
// @Inject lets Dagger know how to create instances of these objects
class UserLocalDataSource @Inject constructor() {
    fun printUserName(){
        Log.e("YM--->","---获取用户姓名")
    }
}
class UserRemoteDataSource @Inject constructor() {  }
@Component
interface ApplicationGraph {
    // The return type  of functions inside the component interface is
    // what can be provided from the container
    fun repository(): UserRepository
}
class DaggerActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_dagger)
        // Create an instance of the application graph
        val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create()
        // Grab an instance of UserRepository from the application graph
        val userRepository: UserRepository = applicationGraph.repository()
        userRepository.printUserName()
    }
}
需要注意的是,写完后需要重新build下才能生成DaggerApplicationGraph类。另外需要注意的是Dagger 在每次收到请求时都会创建 UserRepository 的新实例。所以以下两种实例对象不是一个对象
val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create()
val userRepository: UserRepository = applicationGraph.repository()
val userRepository2: UserRepository = applicationGraph.repository()
assert(userRepository != userRepository2)
如果要是需要多个依赖项目共用一个实例的话,需要引入作用域的概念
四、作用域
修改代码为如下
@Singleton
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) {
    fun printUserName(){
        localDataSource.printUserName()
    }
}
@Singleton
@Component
interface ApplicationGraph {
    // The return type  of functions inside the component interface is
    // what can be provided from the container
    fun repository(): UserRepository
}
五、自定义作用域
暂时不知道自定义作用域的目的,这里仅仅做个记录
 将代码修改为以下可以实现同一目的
@Scope
@MustBeDocumented
@Retention(value = AnnotationRetention.RUNTIME)
annotation class MyCustomScope
@MyCustomScope
@Component
interface ApplicationGraph {
    // The return type  of functions inside the component interface is
    // what can be provided from the container
    fun repository(): UserRepository
}
@MyCustomScope
//@Singleton
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) {
    fun printUserName(){
        localDataSource.printUserName()
    }
}
六、@Binds 和 @Provides
dagger的使用和Hilt的用法一直,这里不再记录,详情参考Hilt一章
七、关于Dagger为什么在Android中要比Hilt复杂
为什么Dagger在Android中会比Hilt用起来复杂?这是因为通常来说,Dagger生成对象需要通过构造函数来生成,但是由于某些 Android 框架类(如 Activity 和 Fragment)由系统实例化,因此 Dagger 无法为您创建这些类。因此生成起来就比较麻烦的多。所以对于这些类必须使用字段注入。举个例子,假设我们想在一个类里面使用Activit对象,我们是没有办法通过构造函数的方式生成这个对象的,比如如下代码
@Inject lateinit var act: Activity
虽然定义了Activity,但是却没有办法去生成它。
 详情参考dagger官网
八、inject(Activity act)的用法
通常的方式是通过一个 inject()函数进行绑定,代码如下
class UserViewModel @Inject constructor(){
    fun test(){
        Log.e("YM","======")
    }
}
@Component
interface UserComponent{
    fun inject(activity: DaggerActivity)
}
class DaggerActivity : AppCompatActivity() {
    @Inject lateinit var useViewModel: UserViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        DaggerUserComponent.create().inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        useViewModel.test()
    }
}
如果不使用fun inject(activity: DaggerActivity)进行绑定,那么使用useViewModel时候就会出现未初始化的问题。这里可以查看下一个生成的代码
@DaggerGenerated
@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
public final class DaggerUserComponent implements UserComponent {
  private final DaggerUserComponent userComponent = this;
  private DaggerUserComponent() {
  }
  public static Builder builder() {
    return new Builder();
  }
  public static UserComponent create() {
    return new Builder().build();
  }
  @Override
  public void inject(DaggerActivity activity) {
    injectDaggerActivity(activity);
  }
  private DaggerActivity injectDaggerActivity(DaggerActivity instance) {
    DaggerActivity_MembersInjector.injectUseViewModel(instance, new UserViewModel());
    return instance;
  }
  public static final class Builder {
    private Builder() {
    }
    public UserComponent build() {
      return new DaggerUserComponent();
    }
  }
}
@QualifierMetadata
@DaggerGenerated
@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
public final class DaggerActivity_MembersInjector implements MembersInjector<DaggerActivity> {
  private final Provider<UserViewModel> useViewModelProvider;
  public DaggerActivity_MembersInjector(Provider<UserViewModel> useViewModelProvider) {
    this.useViewModelProvider = useViewModelProvider;
  }
  public static MembersInjector<DaggerActivity> create(
      Provider<UserViewModel> useViewModelProvider) {
    return new DaggerActivity_MembersInjector(useViewModelProvider);
  }
  @Override
  public void injectMembers(DaggerActivity instance) {
    injectUseViewModel(instance, useViewModelProvider.get());
  }
  @InjectedFieldSignature("com.dagger.application.dagger.DaggerActivity.useViewModel")
  public static void injectUseViewModel(DaggerActivity instance, UserViewModel useViewModel) {
    instance.useViewModel = useViewModel;
  }
}
通过生成的代码可以看出是关联过程的。
九、作用域和子组件
 这一章节不算复杂,这里将代码贴出作为记录
// @Inject lets Dagger know how to create instances of this object
@Singleton
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) {
    fun printUserName(){
//        localDataSource.printUserName()
        remoteDataSource.printUserName()
    }
}
// @Inject lets Dagger know how to create instances of these objects
class UserLocalDataSource @Inject constructor() {
    fun printUserName(){
        Log.e("YM--->","---获取用户姓名")
    }
}
class UserRemoteDataSource @Inject constructor( private val loginService: LoginRetrofitService) {
    fun printUserName(){
        Log.e("YM--->","---remote")
    }
}
class LoginRetrofitService @Inject constructor(){
}
@Module
class NetworkModule {
    // @Provides tell Dagger how to create instances of the type that this function
    // returns (i.e. LoginRetrofitService).
    // Function parameters are the dependencies of this type.
    @Provides
    fun provideLoginRetrofitService(): LoginRetrofitService {
        // Whenever Dagger needs to provide an instance of type LoginRetrofitService,
        // this code (the one inside the @Provides method) is run.
        return LoginRetrofitService()
    }
}
// The "subcomponents" attribute in the @Module annotation tells Dagger what
// Subcomponents are children of the Component this module is included in.
@Module(subcomponents = [LoginComponent::class])
class SubcomponentsModule {}
@ActivityScope
class LoginViewModel @Inject constructor(private val userRepository: UserRepository) {
    fun toast(){
        Log.e("YM","======")
    }
}
@Singleton
@Component(modules = [NetworkModule::class, SubcomponentsModule::class])
interface ApplicationGraph {
    // The return type  of functions inside the component interface is
    // what can be provided from the container
    fun repository(): UserRepository
//    fun inject(activity: Application)
    // This function exposes the LoginComponent Factory out of the graph so consumers
// can use it to obtain new instances of LoginComponent
    fun loginComponent(): LoginComponent.Factory
}
// Definition of a custom scope called ActivityScope
@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class ActivityScope
// Classes annotated with @ActivityScope are scoped to the graph and the same
// instance of that type is provided every time the type is requested.
@ActivityScope
@Subcomponent
interface LoginComponent {
    @Subcomponent.Factory
    interface Factory {
        fun create(): LoginComponent
    }
    fun inject(activity: DaggerActivity)
//    fun activity(): DaggerActivity
}
@Singleton
@Component(modules = [NetworkModule::class, SubcomponentsModule::class])
interface ApplicationGraph {
    // The return type  of functions inside the component interface is
    // what can be provided from the container
    fun repository(): UserRepository
//    fun inject(activity: Application)
    // This function exposes the LoginComponent Factory out of the graph so consumers
// can use it to obtain new instances of LoginComponent
    fun loginComponent(): LoginComponent.Factory
}
// Definition of a custom scope called ActivityScope
@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class ActivityScope
// Classes annotated with @ActivityScope are scoped to the graph and the same
// instance of that type is provided every time the type is requested.
@ActivityScope
@Subcomponent
interface LoginComponent {
    @Subcomponent.Factory
    interface Factory {
        fun create(): LoginComponent
    }
    fun inject(activity: DaggerActivity)
//    fun activity(): DaggerActivity
}
class DaggerApp: Application() {
    val appComponent = DaggerApplicationGraph.create()
}
class DaggerActivity : AppCompatActivity() {
    @Inject
    lateinit var loginViewModel: LoginViewModel
    lateinit var loginComponent: LoginComponent
    override fun onCreate(savedInstanceState: Bundle?) {
        val applicationGraph: ApplicationGraph = (applicationContext as DaggerApp).appComponent
        applicationGraph.repository().printUserName()
        loginComponent = applicationGraph.loginComponent().create()
        // Make Dagger instantiate @Inject fields in LoginActivity
        loginComponent.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        loginViewModel.toast()
    }
}
十、参考链接
- Dagger 基础知识










