博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MVP模式入门(结合Rxjava,Retrofit)
阅读量:4988 次
发布时间:2019-06-12

本文共 7464 字,大约阅读时间需要 24 分钟。

  本文MVP的sample实现效果:

  

  github地址:

 

  

  老规矩,在说对MVP模式的理解之前还是要再谈谈MVC模式,了解了MVC的缺点。我们才知道为什么要用MVP。

  关于MVC的图解,我在网上找到了一些图。如下:

    

 

  MVC模式在开发web或者管理系统中应用很多,我们的View与人交互,人点击鼠标或者输入一些东西时,View会发送相应的指令给Controller,Controller接到指令,再去调用Model的方法去更新数据(大多是对数据的增删改查),Model处理完,View刷新显示

 

  MVC模式的缺点:

    1:在android中,如果我们要用mvc模式,那么每层代表什么呢?

     你可能会说:View对应android的layout.xml,Model对应android中对数据库的操作对网络等操作放在这里进行,Controller对应的则是Activity!

     你说的都对,但是你不觉得这样的对应关系并不好吗,如果layout.xml对应View,那如果我们想动态的控制添加一些视图控件或者改变背景,那么该怎么办呢?

     答曰:在Activity中添加代码。!!!这就是缺点之一所在:Activity既当爹(View)又当妈(Controller),layout.xml代表的View层控制能力太弱。

    2:再看一遍我们的MVC的结构图,View和Model是互相联系的,存在耦合关系,这就给测试维护带来了难度。当我们想更换项目中的某个零件时,缺发现 太难拆下来!这个零件类的方法散布多处。关于MVC的结构图,忘了在哪听过一句经典的话,写三个字母,M,V,C,随便用线或箭头连字母,最后就是MVC的结构图。

 

  说完了MVC,该主角登场了,上我们MVP的结构图。

  

  好处不言而喻,View和Model无法通信了。

  View层只负责与View有关的,操作View层时发出的事件传递给Presenter,Presenter去操作Model,操作完Model,再去通知View相应更新。

  关于MVP的更多概念:

  

  

 

  接下来,看看我们在项目中如何使用MVP模式,这里顺便使用了Retrofit和RXjava,建议你先了解它们的用法。

  首先看我们的需求:输入Github登录名,点击搜索按钮,搜索并显示结果(登录名,昵称, followers,following)

  

  最终的项目结构:

               

   bean类:    

public class User {    private String login;    private String name;    private int followers;    private int following;    public int getFollowers() {        return followers;    }    public void setFollowers(int followers) {        this.followers = followers;    }    public int getFollowing() {        return following;    }    public void setFollowing(int following) {        this.following = following;    }    public String getLogin() {        return login;    }    public void setLogin(String login) {        this.login = login;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

    

    retrofit类主要是封装了利用Retrofit的网络请求 

public interface GithubService {    @GET("/users/{user}")    Observable
getUser(@Path("user") String username);}

   

public class HttpMethods {    public static final String BASE_URL = "https://api.github.com";    private static final int DEFAULT_TIMEOUT = 5;    private Retrofit retrofit;    private GithubService mGithubService;    //构造方法私有    private HttpMethods() {        //手动创建一个OkHttpClient并设置超时时间        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();        httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);        retrofit = new Retrofit.Builder()                .client(httpClientBuilder.build())                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .baseUrl(BASE_URL)                .build();        mGithubService = retrofit.create(GithubService.class);    }    private static class SingletonHolder{        private static final HttpMethods INSTANCE = new HttpMethods();    }    //获取单例    public static HttpMethods getInstance(){        return SingletonHolder.INSTANCE;    }    public void getUser(Subscriber
subscriber ,String loginName){ mGithubService.getUser(loginName) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(subscriber); }}

 

    

  接下来思考我们的MVP模式了,一些从我们的View层开始,我们需要先列出和View相关的方法(不涉及逻辑)。

  1.显示xml的试图

      2.ProgressDialog显示

  3.ProgressDialog消失

  4.显示错误信息

     接下来看具体代码:

  activity_main.xml

 

  BaseView,BasePresentor , BaseModel三个接口 

  

public interface BaseView {    void showProgressDialog();    void hideProgressDialog();    void showText(User userbean);    void showErrorMessage(String text);}

   

public interface BasePresenter
{ void attachView(T view); void detachView(); void searchUser(String loginName);}

   

public interface BaseModel {    void getUser(Subscriber
subscribe,String loginName);}

 

  第二个接口interface BasePresenter<T extends BaseView>正是关键,至于为什么,可以用实现类去解释。

  MainActivity实现BaseView接口,作为View层。 

  

public class MainActivity extends AppCompatActivity implements BaseView {    @InjectView(R.id.tv)    TextView mTextView;    @InjectView(R.id.search_btn)    Button mButton;    @InjectView(R.id.ed_text)    EditText mEditText;    private  ProgressDialog dialog;    private MainPresenter mMainPresenter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.inject(this);        initView();        mMainPresenter=new MainPresenter();        mMainPresenter.attachView(this);    }    /**     * 一些初始化,这里为ProgressDialog的初始化     */    private void initView() {        dialog=new ProgressDialog(this);        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);        dialog.setMessage("正在搜索中");    }    @OnClick(R.id.search_btn)    void search(View view){        mMainPresenter.searchUser(mEditText.getText().toString());    }    @Override    public void showProgressDialog() {        dialog.show();    }    @Override    public void hideProgressDialog() {        dialog.dismiss();    }    @Override    public void showText(User userbean) {        String temp=getResources().getString(R.string.user_format);        String str=String.format(temp,userbean.getLogin(),userbean.getName(),userbean.getFollowers(),userbean.getFollowing());        mTextView.setText(str);    }    @Override    public void showErrorMessage(String text) {        Toast.makeText(this,text,Toast.LENGTH_SHORT).show();    }    @Override    protected void onDestroy() {        super.onDestroy();        if(mMainPresenter!=null)        mMainPresenter.detachView();    }}

 

  当点击Button产生事件时,是将逻辑交给MainPresenter去处理的,对应关系  V  ——>  P

  下面看MainPresenter代码和Model代码。

  

public class MainPresenter implements BasePresenter {    private BaseView mMainView;    private MainModel mModel;    public MainPresenter() {        mModel=new MainModel();    }    @Override    public void attachView(BaseView view) {        mMainView=view;    }    @Override    public void detachView() {        mMainView=null;    }    @Override    public void searchUser(String loginName) {        if(TextUtils.isEmpty(loginName.trim())){            mMainView.showErrorMessage("请输入合法登录名");            return;        }        if (mModel!=null){            mModel.getUser(new Subscriber
() { @Override public void onStart() { //先显示对话框 mMainView.showProgressDialog(); } @Override public void onCompleted() { //请求结束,对话框消失 mMainView.hideProgressDialog(); } @Override public void onError(Throwable e) { //error时 mMainView.showErrorMessage("搜索失败"); } @Override public void onNext(User user) { mMainView.showText(user); } },loginName); } }}

  

public class MainModel implements BaseModel{    @Override    public void getUser(Subscriber
subscriber ,String loginName) { HttpMethods.getInstance().getUser(subscriber,loginName); }}

 

 

  这里的Model实现类较为简单,直接使用了封装好的HttpMethods的方法。(Model可以理解为一个仓库管理员,我们的网络也能理解为一个大的仓库)。

  在MainPresenter中我们其实是使用了Model的方法,即P——>M

  然后用Rxjava的观察者观察结果,再去调用View的方法刷新界面,即P——>V

  

  这时候回过来头来看我们的MVP图,是不是一模一样?(如何想要进阶mvp,可以试试契约类)

       

        

 

  

转载于:https://www.cnblogs.com/xurui1995/p/6021209.html

你可能感兴趣的文章
BZOJ 2648: SJY摆棋子 kdtree
查看>>
Entity Framework
查看>>
第一阶段结对作业验收小学生四则运算
查看>>
理解python可变类型vs不可变类型,深拷贝vs浅拷贝
查看>>
添加数据库的Maven依赖(SqlServer,Oracle)
查看>>
Python Revisited (变量)
查看>>
从本质看海明码——海明码的由来
查看>>
线段树+等差/等比
查看>>
实验二
查看>>
Fedora 安装下载加速插件
查看>>
Leetcode:647. Palindromic Substrings
查看>>
解决Mac下Eclipse模糊的问题
查看>>
【转】js获取对象的所有属性和方法
查看>>
.NET使用本地outlook客户端发送邮件
查看>>
struts2.3.20+spring4.0.2+hibernate4.3.4框架整合
查看>>
MVC详解
查看>>
海洋cms 模板标签手册
查看>>
adt-bundle-windows-x86_32-20140702
查看>>
HTML5小游戏【是男人就下一百层】UI美化版
查看>>
SSH免密登陆
查看>>