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

MVP架构笔记之-DI框架dagger2

程序员文章站 2024-03-15 18:33:00
...

         dagger2在mvp架构开发中主要起到了解耦的作用,我的上一篇文章MVP架构笔记之初探--mvp原理写的是一个最为基础的MVP架构,其实啊,这个架构是耦合的一个架构,我们的view层持有一个MvpPresenter()对象实例;我们的P层构造函数里面又新建了一个m层的对象实例,这样view依赖presenter,presenter又依赖model就是一个紧耦合的架构。

          现在在我们用dagger2对上面的mvp架构进行改进,在这之前先对dagger2进行了解,首先dagger2的官网

https://google.github.io/dagger/    以及dagger2的github开源地址 https://github.com/google/dagger,dagger2几个新属性的价绍:

@Inject   可以注解成员变量和构造函数,如上面的view层持有的p的对象变量和p的构造函数
@Module 可用来注解无法由我们注解构造函数的第三方类、系统类、接口类,如retrofit,okhttp,gson等
@Provides 注解修饰的方法,一般用于@Module注解类中的方法,负责提供具体类型的依赖
@Componet
负责修饰接口或抽象类,提供inject抽象方法等待相应的页面oncreate时实现注入,提供
modules=xxmodule.class链接module,实现@Inject  和@Module中间链接桥的作用

还有一个非必需但很重要的,

@scope :作用域,dagger2给我们提供了一种@Singleton单例,其他的类型需要我们自己定义,比如@ApplicationScope@ActivityScope,@FragmentScope等,定义方式可以如下:

@Scope
@Retention(RUNTIME)
public @interface ActivityScope {}

需要了解更多scope原理请参考文档:http://www.cnblogs.com/tiantianbyconan/p/5095426.html

接下来,先来看一下我们改造过后的项目代码,首先我们看构造函数完成注入的方式activity中:

public class MainActivity extends AppCompatActivity implements MvpContract.View {

    @Inject
    TestPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DaggerMainActivityComponent.create().inject(this);
        setContentView(R.layout.activity_main);
        presenter.toString();
}

    @Override
    public void showData(String data) {
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showload() {

    }
}
public class TestPresenter {
    String temp;

    @Inject
    public TestPresenter() {
        temp = "测试数据";
    }

    public String toString() {
        return temp;
    }
}
@Component
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

为了测试方便,我新建了一个presenter,因为我在presenter中暂时还不想拿model和view对象,如上,我们发现activity的代码变得简单了许多,其中最关键的步骤就是我们开始注解的这一步

DaggerMainActivityComponent.create().inject(this);

这一步事真正实现presenter对象的实例化的,不然你可以把这行代码去掉,看你的presenter会不会报空指针异常,当然我们并没有写DaggerMainAcitivityComponent这类,这个类是我们的链接桥MainActivitiyComponent运行时生成的类,所以我们需要先把工程build一下才能调用这个类。注意:上述案例是在项目的mvpdagger2分支

接下来,我们来看一下当包含module时得实现方式,先看看我们得工程目录,我对代码进行了分包:

MVP架构笔记之-DI框架dagger2

相比于前一个案例,确实复杂了不少,但分得却很明确,framework包下主要定义一些抽象得接口和公用得东西;di包下主要定义了module和component,前面我们也定义了component 的;mvp下对主要功能进行分层,契约类、M层、P层和v层,整个架构的思想如下图:

MVP架构笔记之-DI框架dagger2

可以看到我们得契约类和先前得不太一样了,主要作用是对model和view层进行管理,即我们需要在presenter中处理的类对象,契约类如下:

public interface MainContract {
    //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息
    interface View extends IView {
        void showData(String string);
    }

    //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,即是否使用缓存
    interface Model extends IModel {
        String getData();
    }
}

接下来实现model层:

@ActivityScope
public class MainModel implements MainContract.Model {

    @Inject
    public MainModel() {
        //获取网络数据或者缓存数据
    }

    @Override
    public void onDestroy() {
    }

    @Override
    public String getData() {
        return "来自model层得数据";
    }
}

可以看到我们对构造函数进行了注解,这里要写的原因是和我们module里面的写法有关系,如下:

@Module
public class MainModule {
    private MainContract.View view;

    /**
     * 构建MainModule时,将View的实现类传进来,这样就可以提供View的实现类给presenter
     *
     * @param view
     */
    public MainModule(MainContract.View view) {
        this.view = view;
    }

    @ActivityScope
    @Provides
    MainContract.View provideMainView() {
        return this.view;
    }

    @ActivityScope
    @Provides
    MainContract.Model provideMainModel(MainModel model) {
        return model;
    }

//    @ActivityScope
//    @Provides
//    MainContract.Model provideMainModel() {
//        return new MainModel();
//    }
}

我们写的函数需要给函数提供值,所以注解了构造函数,当然如果换成下面不提供值,直接新建对象的话就不需要提供数据的来源了,自然也不需要@inject model 的构造函数;你可以跑一跑程序试试,两种是一样的效果。在如上两个类中我们都看到了有一个自定义注解@ActivityScope  ,表示只针对当前的Activity 有效,限制作用域范围,注解在类上表示类,注解在方法上表示方法,把modlue都写好了就该我们的连接器component登场了,如下:

@ActivityScope
@Component(modules = MainModule.class)
public interface MainComponent {
    void inject(MainActivity activity);
}

这里是一个接口,暴露了抽象方法给外部,由MainModule提供数据,等着页面来注解,同样在activity里面进行数据的注入操作,如下:

@Inject
    MainPresenter mainPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainComponent.builder()
                .mainModule(new MainModule(this))
                .build()
                .inject(this);

        mainPresenter.getData();
    }
@Override
    public void showData(String string) {
        Log.e("yy", string);
    }

至此,我们就完成了整个主流程的操作。还有一个默认的@scope操作符@Singleton我忘记介绍了,其实和@ActivityScope类似,可以修饰相应的类和方法,如下:

@Singleton
    @Provides
    MainContract.Model provideMainModel(MainModel model) {
        return model;
    }

表示单例model,最后运行一下我们的程序结果如下:

MVP架构笔记之-DI框架dagger2
代码在项目的mvpdagger2module分支,通过这两个案例我们对dagger2的使用有了一个初步的了解,其实dagger2还有更强大的用法,dagger.android,这个我也还没掌握。哈哈,大家可以看下引入规则,dagger2:

implementation 'com.google.dagger:dagger:2.14.1'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'

dagger2.android 需要内外添加:

implementation 'com.google.dagger:dagger-android:2.14.1'
    implementation 'com.google.dagger:dagger-android-support:2.14.1'
    // if you use the support libraries
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1'

最后,给出代码的git地址:

https://github.com/yangyong915/MvpManager-yy

如果你觉得好,一定记得STAR哦。