详细的Dagger2+MVP融合,一行一行分析,一点一点进步,之二

来源:互联网 发布:淘宝开店能挣钱吗 编辑:程序博客网 时间:2024/06/01 17:34

    上一篇我们大致了解了项目的结构组成,这一篇我们来分别说说里面的细节。


    首先,搭建框架,就要根据框架的特点去完成初步的搭建。根据MVP的官网描述,我们首先完成MVP框架的基础构建,每一个activity都是一个V,一个V对应一个Presenter,所以在每一个界面的包下面,就至少包含了三个文件,IXXXConstane(V、P接口描述类)、XXXActivity(V)、XXXPresenter(P),每一个类的职责也必须清晰,XXXActivity主要用来作显示界面使用,不能包含任何逻辑,XXXPresenter主要用来沟通数据模块和V,数据改变了,就应该通知相应的界面控件进行改变,这是MVP框架中很重要的思想,每一个模块都只是完成自己的功能,不能逾越。


    来看代码,在每一个V中都持有P的引用,那么在V中是可以调用P中的逻辑的,但我们一般不这么做,在V中持有P的引用,我们只是为了初始化P,让P和V关联起来,而不是直接去调用P中的逻辑,这点比较重要,不然结构就比较混乱了。比如在MainActivity中,就持有IMainConstane.IMainPresenter的引用,但我们一般不直接调用IMainPresenter中的逻辑:

public class MainActivity extends BaseActivity implements IMainConstane.IMainView {    @Inject    IMainConstane.IMainPresenter mMainPresenter;    private TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.text);        DaggerMainComponent.builder()                .userModelComponent(((MyApplication) getApplicationContext()).getUserModelComponent())                .mainModule(new MainModule(this))                .build()                .inject(this);    }    public void onViewClick(View view) {        switch (view.getId()) {            case R.id.login:                // 这里打印一下用户模块对象的地址,来判断@Singleton单利模式是否有用                mMainPresenter.logUserHashcode();                mMainPresenter.login("", "");                break;            case R.id.view_detail:                startActivity(new Intent(getApplicationContext(), SecondActivity.class));                break;        }    }    @Override    public void setTextMessage(String message) {        if (TextUtils.isEmpty(message)) {            tv.setText("");        } else {            tv.setText(message);        }    }}

    可以看到,我在V中,是没有直接调用P中的逻辑代码的,但有一种情况例外,就是事件交互,在人机进行交互的过程中,我们需要进行一些数据的操作,这个时候直接调用是没问题的。

    我所说的只是“最好不要在V中直接调用P的代码,并不是一定不能,V中调用P的代码会显得结构层次有点乱,但如果业务需要,那也没办法


    看完V,我们再来说说P,P的构造函数中就传递进来两个参数,分别为M和V,这也就是为什么P是整个框架的逻辑处理核心的原因了,因为同时持有两者,那么就可以使用两者暴露出来的接口进行整个逻辑的操作和判断了。

public class MainPresenter implements IMainConstane.IMainPresenter {    private final IMainConstane.IMainView mView;    private final IUserModel mUserModel;    public MainPresenter(IMainConstane.IMainView view, IUserModel usermodel) {        this.mView = view;        this.mUserModel = usermodel;    }    @Override    public void login(String userName, String password) {        mUserModel.login(userName, password, new OnLoginListener() {            @Override            public void loginSuccess() {                mView.setTextMessage("login Success");            }            @Override            public void loginFaile(String message) {                mView.setTextMessage("login Faile");            }        });    }    @Override    public void logUserHashcode() {        mUserModel.logUser();        mUserModel.logOkHttp();        mUserModel.logRetrofit();    }}

    看上面的代码,当界面点击之后,会调用P中的login方法,也就是上面的login方法了,而该方法中则调用的是数据模块中的登录方法,我们跟进去看一下,就会发现调用到了UserModelImpl里面的登录方法,这样,整个逻辑就很清楚了,界面发起数据请求,通过P转到数据层,数据层通过回调接口(OnLoginListener)回调给P,然后P再根据持有的V进行界面的更改,也就是

mView.setTextMessage("login Success");和mView.setTextMessage("login Faile");


    其实在这里是有一个歧义和区别的,你可能注意到了model包下的otherModel,它代表的是你项目中除用户数据模块之外的其它数据模块,比如我应用里面还需要产品数据模块,那么在P中如何将这些数据模块传递进去呢?


    总不能修改P的构造函数,将所有数据模块依次传递进去吧?这样做先不说修改构造函数有多么繁琐,就算有dagger2我也不推荐这样使用。

    我觉得,数据模块因该统一一个入口,然后里面应该分别持有所需模块,然后将统一入口提供给P。当然,这只是我想的,每个人对这个地方的处理可能不一样,有些人喜欢分别传入,也有些人喜欢统一入口方便管理,这就看个人喜好了!


    最好还想看一下数据模块的组成的,但看了一下,觉得没什么好说的,代码写的很详细也简单易懂,主要就是接口编程,一个接口类IUserModel,一个实现类UserModelImpl。


    这个地方不明白的可以私聊我!



源码下载

详细的Dagger2+MVP融合,一行一行分析,一点一点进步,之一

详细的Dagger2+MVP融合,一行一行分析,一点一点进步,之三

详细的Dagger2+MVP融合,一行一行分析,一点一点进步,之四

0 0
原创粉丝点击