项目地址:https://github.com/googlesamples/android-architecture/tree/todo-mvp-dagger/

项目结构

Dagger2是完全静态的、编译时的依赖注入框架,用于Java和Android。
本项目基于MVP和Dagger2。

注:本文假设读者已基本了解Dagger2的使用

源码分析

Application DI

@Component

ToDoApplication源码:

public class ToDoApplication extends Application {

    private TasksRepositoryComponent mRepositoryComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        mRepositoryComponent = DaggerTasksRepositoryComponent.builder()
                .applicationModule(new ApplicationModule((getApplicationContext())))
                .build();

    }

    public TasksRepositoryComponent getTasksRepositoryComponent() {
        return mRepositoryComponent;
    }

}

TasksRepositoryComponent作为Application中属性成员,onCreate()初始一次,那么它应该是一个全局变量。其源码:

@Singleton
@Component(modules = {TasksRepositoryModule.class, ApplicationModule.class})
public interface TasksRepositoryComponent {
    TasksRepository getTasksRepository();
}

通过@Singleton注解可知,TasksRepositoryComponent在注入后,是一个单实例对象,同时又被应用于Appliation中,那么就是一个全局的单例对象。
提供一个获取TasksRepository对象的方法。

@Modules

通过@Component(modules = {TasksRepositoryModule.class, ApplicationModule.class})可知,提供依赖对象的两个类。
先来看下ApplicationModule源码:

@Module
public final class ApplicationModule {

    private final Context mContext;

    ApplicationModule(Context context) {
        mContext = context;
    }

    @Provides
    Context provideContext() {
        return mContext;
    }
}

只是通过 @Provides提供了一个Context对象。而其初始化,需要交由它处显示调用,后面会说。

再来看下TasksRepositoryModule源码:

@Module
public class TasksRepositoryModule {
    @Singleton
    @Provides
    @Local
    TasksDataSource provideTasksLocalDataSource(Context context) {
        return new TasksLocalDataSource(context);
    }

    @Singleton
    @Provides
    @Remote
    TasksDataSource provideTasksRemoteDataSource() {
        return new FakeTasksRemoteDataSource();
    }
}

TasksRepositoryModule提供了两个返回TasksDataSource单实例的方法。@Local、@Remote都使用了@Qualifier来定义,表示对实现相同接口的对象,作区分。

@Inject

注入了上面这两个对象后,而在Component中,要求注入的是TasksRepository对象,再来看下TasksRepository的相关源码:

    @Inject
    TasksRepository(@Remote TasksDataSource tasksRemoteDataSource,
            @Local TasksDataSource tasksLocalDataSource) {
        mTasksRemoteDataSource = tasksRemoteDataSource;
        mTasksLocalDataSource = tasksLocalDataSource;
    }

发现TasksRepository的构造,依赖于分别使用了@Remote和@Local的两个对象。

结合Dagger2生成的代码进行分析

回过头来看ToDoApplication#onCreate()中:

mRepositoryComponent = DaggerTasksRepositoryComponent.builder()
                .applicationModule(new ApplicationModule((getApplicationContext())))
                .build();

DaggerTasksRepositoryComponent就是Dagger2自动编译生成的一个类。其源码:

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerTasksRepositoryComponent implements TasksRepositoryComponent {
  private Provider<TasksDataSource> provideTasksRemoteDataSourceProvider;

  private Provider<Context> provideContextProvider;

  private Provider<TasksDataSource> provideTasksLocalDataSourceProvider;

  private Provider<TasksRepository> tasksRepositoryProvider;

  private DaggerTasksRepositoryComponent(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.provideTasksRemoteDataSourceProvider =
        ScopedProvider.create(
            TasksRepositoryModule_ProvideTasksRemoteDataSourceFactory.create(
                builder.tasksRepositoryModule));

    this.provideContextProvider =
        ApplicationModule_ProvideContextFactory.create(builder.applicationModule);

    this.provideTasksLocalDataSourceProvider =
        ScopedProvider.create(
            TasksRepositoryModule_ProvideTasksLocalDataSourceFactory.create(
                builder.tasksRepositoryModule, provideContextProvider));

    this.tasksRepositoryProvider =
        ScopedProvider.create(
            TasksRepository_Factory.create(
                provideTasksRemoteDataSourceProvider, provideTasksLocalDataSourceProvider));
  }

  @Override
  public TasksRepository getTasksRepository() {
    return tasksRepositoryProvider.get();
  }

  public static final class Builder {
    private TasksRepositoryModule tasksRepositoryModule;

    private ApplicationModule applicationModule;

    private Builder() {}

    public TasksRepositoryComponent build() {
      if (tasksRepositoryModule == null) {
        this.tasksRepositoryModule = new TasksRepositoryModule();
      }
      if (applicationModule == null) {
        throw new IllegalStateException(
            ApplicationModule.class.getCanonicalName() + " must be set");
      }
      return new DaggerTasksRepositoryComponent(this);
    }

    public Builder tasksRepositoryModule(TasksRepositoryModule tasksRepositoryModule) {
      this.tasksRepositoryModule = Preconditions.checkNotNull(tasksRepositoryModule);
      return this;
    }

    public Builder applicationModule(ApplicationModule applicationModule) {
      this.applicationModule = Preconditions.checkNotNull(applicationModule);
      return this;
    }
  }
}

内部使用了Builder模式。有一个内部类Builder。Builder中有TasksRepositoryModule和ApplicationModule的注入方法。build()返回TasksRepositoryComponent。TasksRepositoryComponent的初始化,会调用initialize(builder),内部主要是解析对@Provides,注入各对象需要的Provider。Provider中就一个方法:T get()。如这里的获取TasksRepository:

public TasksRepository getTasksRepository() {
    return tasksRepositoryProvider.get();
}

Activity DI

再简单分析下 Activity中的依赖注入。
每个业务功能模块包下都有一个Component,一个Module

tasks模块

TasksActivity主要代码:

public class TasksActivity extends AppCompatActivity {

    @Inject
    TasksPresenter mTasksPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tasks_act);

        TasksFragment tasksFragment =
                (TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
        if (tasksFragment == null) {
            // Create the fragment
            tasksFragment = TasksFragment.newInstance();
            ActivityUtils.addFragmentToActivity(
                    getSupportFragmentManager(), tasksFragment, R.id.contentFrame);
        }

        // Create the presenter
        DaggerTasksComponent.builder()
                .tasksRepositoryComponent(((ToDoApplication) getApplication()).getTasksRepositoryComponent())
                .tasksPresenterModule(new TasksPresenterModule(tasksFragment)).build()
                .inject(this);

        // Load previously saved state, if available.
        if (savedInstanceState != null) {
            TasksFilterType currentFiltering =
                    (TasksFilterType) savedInstanceState.getSerializable(CURRENT_FILTERING_KEY);
            mTasksPresenter.setFiltering(currentFiltering);
        }
    }
}

DaggerTasksComponent由TasksComponent生成。指定TasksPresenterModule。
这里重要说下inject()的实现,跟踪进去,发现DaggerTasksComponent#inject():

  public void inject(TasksActivity activity) {
    tasksActivityMembersInjector.injectMembers(activity);
  }

浏览代码,发现有两个MembersInjector:tasksPresenterMembersInjector和tasksActivityMembersInjector。
tasksActivityMembersInjector的生成,因在TasksActivity中,使用了@Inject;
tasksPresenterMembersInjector的生成,因在TasksPresenter中有

  @Inject
    void setupListeners() {
        mTasksView.setPresenter(this);
    }

基本就分析到这了。

Component中指定注入方,在注入方创建DaggerComponent,并调用注入方法,以注入使用了@Inject的对象和方法

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐