欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android:dagger扩展库

程序员文章站 2022-04-12 20:23:27
概述 之前我们使用dagger注入时,都需要activity、fragment等宿主在component中注册,比如: ((SomeApplicationBaseType)...

概述

之前我们使用dagger注入时,都需要activity、fragment等宿主在component中注册,比如:

((SomeApplicationBaseType) getContext().getApplicationContext())
        .getApplicationComponent()
        .activity(this)
        .build()
        .inject(this);

这样之后才可以使用该component中的依赖实例(也可以是父组件中能拿到的),随着开发的深入,这类代码越来越多,很不利于重构,同时也打破了依赖注入的核心原则:一个类不应该知道如何注入它。

Dagger.Android库是Dagger库的补充,dagger.android中的类提供了一种简化此模式的方法,从而在一定程度上避免了上述问题的发生。

使用流程

1.在ApplicationComponent中注入AndroidInjectionModule,如果项目中用到v4包的Fragment,还需注入AndroidSupportInjectionModule.建议把两个Module都注入ApplicationComponent中:

@Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule,...})
public interface ApplicationComponent {
    void inject(MyApplication application);
} 

2.创建Android库的核心类(Activity、Fragment、Service、IntentService、BroadcasReceiver),需要注意的就是:AndroidInjection.inject(T)方法的调用位置

在Activity、Service及IntentService的onCreate()中,super.onCreate()方法以前。 在Fragment中onAttach()中,super.onAttach()方法以前。如果是v4包的Fragment,应调用AndroidSupportInjection.inject()方法。 在BroadcastReceiver的onReceive()中,super.onReceive之前调用。

3.创建子组件 - @Subcomponent,其继承自AndroidInjector,而T就是step2创建的Android库的类型

@Subcomponent
public interface CoffeeReceiverSubcomponent extends AndroidInjector {
    @Subcomponent.Builder
    public abstract class Builder extends AndroidInjector.Builder {

    }
}

4.创建Module,其subcomponents属性值就是3创建的子组件。在其内必须声明一个抽象方法,该抽象方法返回AndroidInjector.Factory<?>实例,而其参数为3创建的XxSubcomponent.Builder实例。

@Module(subcomponents = CoffeeReceiverSubcomponent.class)
public abstract class CoffeeModule {

    @Binds
    @IntoMap
    @BroadcastReceiverKey(CoffeeReceiver.class)
    abstract AndroidInjector.Factory bind(CoffeeReceiverSubcomponent.Builder builder);
}  

5.将创建的Module注入到ApplicationComponent中,即把其添加至ApplicationComponent的modules属性列表

@Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule.class,  CoffeeModule.class, ...})
public interface TodoComponent extends AndroidInjector {
    @Component.Builder
    abstract class Builder extends AndroidInjector.Builder {
    }
}

6.创建自定义Application,继承了DaggerApplication,因为dagger把该添加的DispatchingAndroidInjector添加进去了。但是,并没有实现v4包的HasSupportFragmentInjector,这里需要手动添加进去。

public class TodoApplication extends DaggerApplication implements HasSupportFragmentInjector{

    @Inject
    DispatchingAndroidInjector fragmentSupportInjector;

    public void onCreate() {
        super.onCreate();
    }

    @Override
    protected AndroidInjector applicationInjector() {
        return DaggerTodoComponent.builder().create(this);
    }

    @Override
    public AndroidInjector supportFragmentInjector() {
        return fragmentSupportInjector;
    }
}

注意:只有当BroadcastReceiver在AndroidManifest.xml中注册时,才能使用DaggerBroadcastReceiver。 当在动态注册BroadcastReceiver时,推荐使用构造函数注入。

官方demo使用方式

官方demo中的使用方式简洁方便,主要是使用了一个注解—@ContributesAndroidInjector

@Target(METHOD)
public @interface ContributesAndroidInjector {
  // 要注入到生成的dagger.Subcomponent中的Module。
  Class[] modules() default {};
}

官方文档对它是这么解释的:为其注解的方法生成相应的AndroidInjector。该注射器是 dagger.Subcomponent的实现

此注释必须应用于返回具体的Android框架类型(例如:FooActivity、BarFragment、MyService等)的Module中的抽象方法。 该方法应该没有参数。

具体可看官方例子mvp-dagger
1.自定义一个application,继承DaggerApplication:

public class ToDoApplication extends DaggerApplication {
    @Inject
    TasksRepository tasksRepository; // component中暴露出来

    @Override
    protected AndroidInjector applicationInjector() {
        return DaggerAppComponent.builder().application(this).build();
    }
}

2.创建一个管理全局的component:

@Singleton
@Component(modules = {TasksRepositoryModule.class,
        ApplicationModule.class,
        ActivityBindingModule.class,
        AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector {

    TasksRepository getTasksRepository();

    // Gives us syntactic sugar. we can then do DaggerAppComponent.builder().application(this).build().inject(this);
    // never having to instantiate any modules or say which module we are passing the application to.
    // Application will just be provided into our app graph now.
    @Component.Builder
    interface Builder {

        @BindsInstance
        AppComponent.Builder application(Application application);

        AppComponent build();
    }
}

3.创建一个ActivityBindingModule用于管理所有应用内的activity(子组件)

@Module
public abstract class ActivityBindingModule {
    @ActivityScoped
    @ContributesAndroidInjector(modules = TasksModule.class)
    abstract TasksActivity tasksActivity();

    @ActivityScoped
    @ContributesAndroidInjector(modules = AddEditTaskModule.class)
    abstract AddEditTaskActivity addEditTaskActivity();

    @ActivityScoped
    @ContributesAndroidInjector(modules = StatisticsModule.class)
    abstract StatisticsActivity statisticsActivity();

    @ActivityScoped
    @ContributesAndroidInjector(modules = TaskDetailPresenterModule.class)
    abstract TaskDetailActivity taskDetailActivity();
}

4.每个activity都可以再通过module属性继续提供依赖或子组件

@Module
public abstract class TasksModule {
    @FragmentScoped
    @ContributesAndroidInjector
    abstract TasksFragment tasksFragment();

    @ActivityScoped
    @Binds abstract TasksContract.Presenter taskPresenter(TasksPresenter presenter);
}

如上的tasksFragment()中 @ContributesAndroidInjector也可以有module继续依赖下去

TasksRepositoryModule可以当做一个全局的数据module,ApplicationModule可以提供一些全局实例,如网球请求的client等等,AndroidSupportInjectionModule则是使用v4包时需要注入的。

总结

扩展库可以使dagger的使用更为简单方便,具体的需要查看官方demo学习后多加练习细细体会