MVP模式-传统-添加dagger2-方便扩展的mvp(原创最全

2017-07-02  本文已影响36人  品味与回味

开始讲之前希望大家懂一个概念 上通配符 下通配符<? entends *><? super *> 希望大家了解。这里我就不说了 如果有需要大家可以留言,我在写一个具体专题去讲讲。
还有一个是mvp的大概了解。如果一点都不熟悉,那么您可能会看的比较吃力一些。

1传统的mvp

首先要先理解最开始mvp的最大作用就是解耦,降低每个之间的联系 所以我们做的做作用就是
1 建立view的接口 Iview,这个接口的作用就是一点 让 view和P之间建立联系,
下面我在啰嗦一点MVP这三个模块的相互之间的作用

modle:它负责处理应用程序的数据部分。
View:它负责在屏幕上设置特定数据的视图。
p:它是连接一个模型和一个视图的桥梁。

有不懂的 我给你解释一下
View的唯一职责是依靠p的指示绘制UI(通过什么? 当然是接口 啊)
modle和View没有直接通信。然后通过P勾勾搭搭。
P 我要重点说一下 , 他的职责就是根据设计view需要的获取数据给modle。另外还有一些
特别的事件要去通知view去更新页面

下面来具体demo

我们来写一个接口(很简单的了解就行)
<pre>
public interface ILoginView {
void showLoading();
void hideLoading();
void showError(String msg);
void LoginSuccess();
}
</pre>

这是我们写的一个接口 用于 view和P之间的联系

我们现在view中实现他
<pre>
public class LoginActivity extends AppCompatActivity implements ILoginView {

略很多。

public void login(View view) {
loginPersenter.login(userName.getText().toString().trim(),password.getText().toString().trim());

}这个就是接口的实现方法

</pre>

接下来我们来写model,这个是用于P中view中获取的数据和model交互。

<pre>
public interface ILoginModel {

void login(String userName, String password,LoginListener listener);

interface LoginListener {
void loginSuccess();
void loginFailed(String msg);
}
}

public class LoginModelImpl implements ILoginModel {

@Override
public void login(String userName, String password, LoginListener listener) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (userName.equals("flyou") && password.equals("553274238")) {
listener.loginSuccess();
} else {
listener.loginFailed("用户名密码错误");
}
},2000);
}
}
</pre>

然后我去们写一个P
<pre>
public class LoginPersenter {
private ILoginView loginView; 作为参数。用来P和view的绑定,来实现一种关系上的联系
private ILoginModel loginModel;model

public LoginPersenter(ILoginView loginView) {
this.loginModel=new LoginModelImpl();
this.loginView = loginView;
}
public void login(final String userName, final String password){
loginView.showLoading();

        loginModel.login(userName, password, new ILoginModel.LoginListener() {
            @Override
            public void loginSuccess() {
                loginView.hideLoading();
                loginView.LoginSuccess();
            }

            @Override
            public void loginFailed(String msg) {
                loginView.hideLoading();
                loginView.showError(msg);
            }
        });
    }
   }

}

</pre>

大家可以看到。当在view中有点击事件的时候 ,会调用p的login方法,并且吧editview的数据传递进去(账户密码),然后会调用view自身实现的showLoading()方法。给进来的数据会交给
loginModel的方法。然后有返回数据的时候在通过loginView的方法进行绘制页面。 这个p就相当于一个中转货运站。 数据交互,页面怎么去更新都先告诉我,然后由P去告诉model怎么去处理数据、。view怎么去具体的更新页面。 说道这里,相信大家有一个大概的印象,那么下面来一点难度了 ,我们想要体现一下 自己能力了。 我们用dagger2

2 在添加了dagger2时候怎么去用MVP

说道这里的时候 给大家提前一个思考的环节(我们绑定的时候 还用接口 联系 P吗? 好多人说mvp的类多。写的多。我们可不可以简单一下?能不能不用构造方法。能不能写一个基类或者可以继承的类。方便去扩展呢? 带着这个疑问 我们来进入下面的环节)

这个换件 不讲dagger2(想了解的可以留言。看状况是不是要单独去讲解。这里你知道dagger2是一种注释就可以。就是我不用new了。就可以获得我想要的对象)

开始正题。 我们现在都用到了dagger2,还用到了 接口去绑定 ,哎 好掉价呀。怎么办呢 我们来想一想(这里要用到了 通配符了呦)
我决定要写一个子类P

<pre>

public class Presenter<T extends Presenter.View> {

private T view;

public void setView(T view) {
this.view = view;
最精髓的一个方法。 这个就是绑定
}

public T getView() {
return view;
}

public void initialize() {

}

public void terminate() {

}

public interface View {
这个是我用来更新每个页面的方法。当然是在具体的情况的时候去填写方法。然后用公用的时候你现在就可以去填写 比如 有转圈(就可以写 void showGenxin() 理解就好。)
}
}
好吧 我在多嘴多说一点 怕大家理解不到我说的通配符的概念。 我这里的T extends Presenter.View的作用就是告诉程序这个P是Presenter.View这个接口的子类

</pre>
下面 让我们是实现一个去了解一下
[里面有一个部分rxjava2的代码。请搜本人的rxjava的学渣系列]
<pre>

public class CharactersPresenter extends Presenter<CharactersPresenter.View> {
(CharactersPresenter.View这个就是Presenter.View接口的一个子类)
private GetCharacters getCharacters;

@Inject public CharactersPresenter(GetCharacters getCharacters) {

this.getCharacters = getCharacters;

}

@SuppressWarnings("unchecked") @Override
public void initialize() {
super.initialize();
this.getCharacters.execute(new GetCharacterListObserver());
}

@Override public void terminate() {
super.terminate();
getCharacters.dispose();
setView(null);
}

private class GetCharacterListObserver extends UseCaseObserver<List<Character>> {

@Override public void onComplete() {
  super.onComplete();
  getView().hideLoading();
}

@Override public void onError(Throwable e) {
  super.onError(e);
}

@Override public void onNext(List<Character> characters) {
  super.onNext(characters);
  getView().showCharacters(characters);
}

}

public interface View extends Presenter.View {

void showCharacters(List<Character> characters);

void hideLoading();

这两个方法就是我实现这个接口的时候 我要实现的特别的方法。 最这个view 有用的方法

}
</pre>

然后 到了关键的时刻。 我要要去绑定了。

在avtivity中 我要要怎么做
<pre>

@Inject CharactersPresenter presenter; 不懂dagger2的 不需要理解。 你知道这个就是我声明实例化了即可, 然后在oncreat中调用下面的方法
当然这个avtivity implements CharactersPresenter.View {
presenter.setView(this);
presenter.initialize();

</pre>
哈哈 相信你已经看懂了。这个精妙的地方。我们不需要在重复的开写新的I***的view的接口,只需要在P中去写就完成了。 他的最大的贡献就是节省代码。让你的代码看着很舒服。

3 当写第三点的时候 你要对 dagger2 rxjava2 等都要有点了解了。 毕竟我是在这两种情况下的扩展。节省代码量

在我开始下面的情况下的时候 我上面说的基类P。其实并不完善。在复杂的情况下就有点鸡肋了。怎说呢。 我用到了通配符。这个概念。 他让我在扩展的时候能够很好的实现。但是一层还是不太够的,因为这里的MODEL我有一层 就是获取数据显示,并不复杂。 但是在复杂的程序的时候 ,数据库。后台服务。第三方的很多 都是数不胜数。我们怎么办?在每个具体的P实例化的时候去注视吗?这样代码重复两太大。 有人说 可以用基类去注释呀。 这里我要说 这是不行的。注释的参数我们获取不到,这个P 设计的时候就是为了绑定。,让具体的P去继承的。 所以构造方法没法去实现。并且。注释的(dagger2也不会注释Presenter,说道这里。dagger2还是需要大家去学习的要不这里你就会觉得去听天书。) 在application中我会提前把一些对象去注释掉。在我需要的时候去注入。直接可以用

就像这样
<pre>
@Provides
Repository provideCharacterRepository(DataSource dataSource) {
return new CharacterRepository(dataSource);
}
</pre>

你不需要上面这个方法的作用。他就是告诉你。通过new CharacterRepository(dataSource);获取到了Repository ,在你需要的时候可以用到。而之前那个P ,首先他是基类 ,

这个P 很明显没有办法这样去用。因为P只是一个基类。(考虑一下)

上一篇下一篇

猜你喜欢

热点阅读