在大学时学过SSH,从那时知道spring的核心,就是IOC控制反转,听起来也是莫名其妙,当时也不知道有什么用,就明白一个DI依赖注入,当然spring在java上是很重要的内容,近段时间也用spring mvc来搭建一个网站,确实还蛮好玩的。

dagger2则是android上的依赖注入手段,通过注释@Inject就可以new创建出一个对象,而该对象里面所依赖的对象,都统统交给dagger2处理,dagger2不需要反射,是事先预编译的结果,可以在build里查看,简单的说我们不需要为创建对象苦恼。

定义

dagger2常用几个注释

@Component @Module @Provides

Application层

在Component里是为了将需要的对象公开接口,否则会在activity中用到application层的对象找不到

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {

    RetrofitClient getRetrofitClient();  // 公开接口
}

App模块会提供公用的Application和RetrofitClient

@Module
public class AppModule {

    Application app;

    public AppModule(Application app) {
        this.app = app;
    }

    @Provides
    public Application providesApp() {
        return app;
    }

    /**
     * 创建一个Retrofit Service
     */
    @Provides
    public RetrofitClient provideService() {
        return new RetrofitClient();
    }
}
Activity层

Scope是为了保证对象与Activity生命周期

/**
 * 作用域
 * Created by 剑指锁妖塔 on 2016/4/7.
 */
@Scope
public @interface ActivityScope {
}

DemoComponent会依赖于AppComponent,modules模块会定义在DemoModule

@ActivityScope
@Component(modules = DemoModule.class, dependencies = AppComponent.class)
public interface DemoComponent {

    DemoActivity inject(DemoActivity activity);
}

DemoActivity用到的DemoPresenter,将会由DemoModule来@Provides提供,在DemoPresenter里会用到RetrofitClient,这个参数就是从AppComponent依赖而来

@Module
public class DemoModule {

    public DemoModule() {

    }

    @Provides
    DemoPresenter providesPresenter(RetrofitClient client) {
        return new DemoPresenter(client);
    }
}
Presenter层

其实DemoPresenter在构造函数时@Inject也同样可以将RetrofitClient引入

/**
 * demo的业务逻辑
 * Created by 剑指锁妖塔 on 2016/6/20.
 */
public class DemoPresenter implements ViewPresenter<DemoViewImpl> {

    DemoViewImpl viewImpl;
    RetrofitClient client;

    public DemoPresenter(RetrofitClient client) {
        this.client = client;
    }

    @Override
    public void setViewImpl(DemoViewImpl view) {
        this.viewImpl = view;
    }

    public void test() {
        client.getInstance(Api.class).getInfo()
                .subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(s -> {
                    Logger.w(s);
                    viewImpl.getString(s);
                }, r -> Logger.e(r.getMessage()));
    }
}

使用

以上就是整个项目里dagger2的模块定义划分,然后就是如何在项目里依赖注入

app

在application里先建立一个AppComponent

public class App extends Application {

    static AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();  
        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();
    }

    public static AppComponent getAppComponent() {
        return appComponent;
    }
}
activity

activity若想使用依赖注入,必需就让activity开始时就引入DaggerDemoComponent,否则无关联依赖必失败

public class DemoActivity extends AppCompatActivity implements DemoViewImpl {

    @BindView(R.id.demo_id)
    protected TextView pT;

    @Inject
    DemoPresenter presenter; // 依赖注入的对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo);
        ButterKnife.bind(this);

        DaggerDemoComponent.builder()
                .appComponent(App.getAppComponent())
                .demoModule(new DemoModule()).build().inject(this);
        presenter.setViewImpl(this);
    }

    /**
     * retrofitTest
     */
    @OnClick(R.id.demo_btn)
    void test() {
        presenter.test(); // 使用该实例的方法
    }

    @Override
    public void getString(String s) {
        pT.setText(s);
    }
}



源代码DaggerDemo

dagger2的原理在许多博客有详细说明源码分析,我这不入流就算了

学这个dagger2的过程中很容易从入门到放弃,像控制反转、依赖的内容是交由系统去处理,是确实比较难去看代码去理解,我在自己一个app里用这种依赖注入的框架,的确在模块化的解耦上有很大帮助,但会发现完成一组功能就要创建很多类,总得来说适合的才是最好的