Dagger的使用一

一、前言

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()
    }
}

十、参考链接

  1. Dagger 基础知识
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值