Hello MVP:Android MVP架构

QuibblerQuibbler 2020-08-13 约 13 分钟 1667 次阅读

Android MVP架构

总结一下MVP架构,谈谈自己对MVP的理解。MVP确实可以在一定程度上减少代码耦合,将View和数据业务分离出来,但是为了MVP而MVP反而会让逻辑更加混乱。

Demo:GitHub/quibbler01/HelloMVP

1、MVP概念

MVP是Model-View-Presenter的简称,即模型-视图-表示器。

1.1、来源

最早在2000年就由IBM旗下的子公司Taligent提出来MVP的概念,当时是针对C++和Java的编程模型。属于MVC模式的变种,目的是为了将UI和业务逻辑剥离。

1.2、M-V-P

M:模型(Model),专注于数据的处理。

V:视图(View),专注于处理数据的可视化以及用户交互。

P:逻辑(Presenter),“逻辑”用于交互与数据传输。

1.3、为什么用MVP

最深的体会是自己写过小程序,那时候也不懂MVP。各种代码,业务逻辑全部挤在一个Activity里面,光是一个Activity就有2000多行代码。定义的各种方法、变量都塞到一个Java类中,后面修改和维护起来会越来越难,虽然自己写的代码对“全局”还是有比较深的印象,但是换个人呢?项目开发中如果所有人都往Activity/View中塞代码,那样最终越来越难以迭代和维护!

所以通过MVP架构,可以将代码很好的组织起来,View的专门负责UI显示,逻辑放到Presenter,数据请求处理放到Model中。层次鲜明代码整体逻辑也比较清晰,不管是项目的功能迭代开发,开始维护都会大大降低难度。

        第一次接触项目代码,就是自己从View层逐渐摸索到Presenter层,再到数据Mode层,对整体的项目结构有一个宏观的了解,MVP架构的项目上手会比较容易。

2、MVP优缺点

MVP比没有MVP要好,但是也有不足。

2.1、优点

①符合单一职责原则:M-V-P三层各司其职

②结构清晰,利于项目维护。

③Presenter复用非常方便,功能扩展。项目增加新功能的时候都没动Presenter层,只是在Model中进行开发新增了一种数据。

④便于单元测试。还没用到过Android Unit单元测试

2.2、缺点

①最明显的缺点就是interface接口太多,需要定义很多Callback回调接口。增加代码量。

②内存泄漏隐患,Presenter持有View的引用,而且Presenter大多数写成单例,如果没有释放Presenter持有的引用,即有可能导致内存泄漏!

3、Demo

举个例子,以Hello World!为例,如何改造成MVP。实际小项目上千万不要过度MVP,没必要把简单的问题搞复杂!

3.1、View

就是Activity,其中的TextView更新数据。持有Presenter单例,通过这个实例请求。

public class MainActivity extends AppCompatActivity implements IView {
    private Presenter mPresenter;
    private TextView mTextView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPresenter = Presenter.getInstance();
        initView();
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.unSubscribe();
    }
    
    private void initView() {
        mTextView = findViewById(R.id.text);
        mPresenter.subscribe(this);
    }
    
    @UiThread
    @Override
    public void showTextMessage(String message) {
        mTextView.setText(message);
    }
}

IView层接口,给Presenter回调,更新界面使用。

public interface IView {
    public void showTextMessage(String message);
}

3.2、Presenter

负责处理View层的请求,从Model层获取数据,再更新View层。

public class Presenter {
    private static volatile Presenter sPresenter;
    private IView mViewCallback;
    private IModel mModel;
    private Handler mHandler = new Handler(Looper.getMainLooper());
    
    private Presenter() {
        mModel = new Model();
    }
    
    public static Presenter getInstance() {
        if (sPresenter == null) {
            synchronized (Presenter.class) {
                if (sPresenter == null) {
                    sPresenter = new Presenter();
                }
            }
        }
        return sPresenter;
    }
    
    private Timer mTimer = new Timer();
    @MainThread
    public void subScribeMessage() {
        //应该使用线程池
        new Thread(new Runnable() {
            @Override
            public void run() {
                getMessageInternal();
                mTimer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        getMessageInternal();
                    }
                }, 0, 1000);
            }
        }).start();
    }
    
    public void unSubscribeMessage() {
        mTimer.cancel();
    }
    
    @WorkerThread
    private void getMessageInternal() {
        final String message = mModel.getMessage();
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (null != mViewCallback) {
                    mViewCallback.showTextMessage(message);
                }
            }
        });
    }
    
    @MainThread
    public void subscribe(@NonNull IView viewCallback) {
        mViewCallback = viewCallback;
        subScribeMessage();
    }
    
    @MainThread
    public void unSubscribe() {
        mViewCallback = null;
        unSubscribeMessage();
    }
}

3.3、Model

模拟从网络等地方获取数据,耗时操作。

public class Model implements IModel {
    private Calendar mCalendar;
    private SimpleDateFormat dateFormat;
    
    public Model() {
        mCalendar = Calendar.getInstance();
        dateFormat = (SimpleDateFormat) SimpleDateFormat.getDateTimeInstance();
    }
    
    @WorkerThread
    @Override
    public String getMessage() {
        return getMessageFromServer();
    }
    
    @WorkerThread
    private String getMessageFromServer() {
        mCalendar.setTimeInMillis(System.currentTimeMillis());
        return "Hello World!\n\n\n" + dateFormat.format(mCalendar.getTime());
    }
}

IModel回调接口,给Presenter使用

public interface IModel {
    public String getMessage();
}

4、TheMVP

MVP架构的一个变种。TheMVP使用Activity作为Presenter层来处理代码逻辑,通过让Activity包含一个ViewDelegate对象来间接操作View层对外提供的方法,从而做到完全解耦视图层。

不详细展开,以后再深入学习一下。GitHub:kymjs/TheMVP

参考博客:

        用MVP架构开发Android应用

        Android MVP 详解(上)

        Android MVP 详解(下)

        Android开发之MVP模式

        菜鸟教程 > Android 开发中的 MVP 实现

        浅谈Android中的MVP架构

GitHub > Android MVP

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w