美文网首页
Android中使用MVP的简单例子

Android中使用MVP的简单例子

作者: 132xin | 来源:发表于2020-08-03 22:34 被阅读0次

    MVP是一种框架,应该通过学习其是思想,然后进行实践,每个人可能有不同的实现方法,以下是我封装的简单例子。
    因为每一个Presenter和View都有一些公共的方法,所以先将其抽取出来,定义Presenter和View的公共父类


    image.png

    IPresenter:定义一个绑定View的方法,让子类去实现

    /**
     * 因为我们需要在BasePresenter中拿到 View的对象,所以定义个接口给BasePresenter的继承
     * @param <V>
     */
    public interface IPresenter<V extends BaseView> {
         void attachView(V View);
    }
    
    

    BaseView中可以做一些View共同的方法,例如加载数据失败时,刚开始加载数据时。

    package com.example.hp.mvptest.base;
    
    /**
     * 这个是所有View实现的基类
     * 可以定义一些View的通用的方法
     */
    public interface BaseView {
        //加载数据失败时
          void loadingFailed();
    
    }
    

    接下来定义一个BasePresnter,实现IPresenter的接口,并且通过弱引用持有View,因为防止View被销毁的时候,Presenter还持有View的引用,导致View不能释放,导致内存泄露。

    /**
     * Presenter的基类,提供绑定View和解绑View的方法
     * 为了防止内存泄露,通过弱引用的方式来持有View
     */
    public abstract  class BasePresenter<V extends BaseView> implements IPresenter<V> {
    
        private WeakReference<V> view;
    
        @Override
        public void attachView(V viewInstance) {
            view = new WeakReference<>(viewInstance);
        }
    
        public WeakReference<V> getView() {
            return view;
        }
    
    }
    
    

    接下来定义一个IView的接口,继承了BaseView,这样在具体View的类中只需要实现IView接口就可以了,不需要继承BaseView,不建议使用抽象类,因为Java不支持多继承。

    /**
     * 定义一个View的接口,定义一个让Presenter更新UI的方法
     */
    public interface IView extends BaseView {
        void loadingView(Object string);
    }
    

    接下来就是一个BaseActivity,为什么要定义这个类呢?因为没一个View都需要实例化一个Presenter的对象,并且绑定View,所以定义一个BaseActivity其中继承了AppCompatActivity,实现了IView,这里可以看出为什么上面的IView要用接口,而不是抽象类。并且定义一个抽象方法:createPresenter(),要求其子类必须实现,初始化Presenter。

    /**
     * Activity都要继承该类
     * @param <V>
     * @param <P>
     */
    public abstract  class BaseActivity<V extends BaseView,P extends BasePresenter<V>> extends AppCompatActivity implements IView {
        private P mPresenter;
        @SuppressWarnings("unchecked")
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mPresenter=createPresenter();
            if (mPresenter!=null){
                //绑定View
                mPresenter.attachView((V) this);
            }
        }
    
        /**
         * 加载失败的处理
         */
        @SuppressLint("ShowToast")
        @Override
        public void loadingFailed() {
            Toast.makeText(this,"加载失败",Toast.LENGTH_SHORT);
        }
        /**
         * 要求子类创建Presenter
         */
        protected abstract P createPresenter();
    
        public P getPresenter() {
            return mPresenter;
        }
    }
    
    

    很多时候我们View可能是Fragment,但是只需要将继承AppCompatActivity,改成Fragment就可以了。

    接下来我就是使用了:


    image.png

    Activity:

    @SuppressLint("Registered")
    public class TestActivity extends BaseActivity<IView, TestPresenter> implements View.OnClickListener {
        Button button;
        TextView textView;
        private TestPresenter mTestPresenter;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.text_layout);
            button=findViewById(R.id.button);
            textView=findViewById(R.id.textView);
            mTestPresenter = getPresenter();
            button.setOnClickListener(this);
        }
    
        @Override
        protected TestPresenter createPresenter() {
            return new TestPresenter();
        }
    
        @Override
        public void loadingView(Object string) {
            textView.setText((String)string);
        }
    
        @Override
        public void onClick(View v) {
            if ((v.getId())==R.id.button){
                mTestPresenter.getData();
            }
    
        }
    }
    
    

    Model:

    /**
     * 因为Model在获取到数据之后,可以通过RxJava来响应,通知Presenter,所以不写接口回调
     */
    public  class TestModel {
        public Observable<String> getDataModel(){
            Observable<String> observable=Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                    emitter.onNext("恭喜您,数据加载成功");
                }
            });
            return  observable;
        }
    }
    
    

    Presenter

    class TestPresenter extends BasePresenter<IView> {
    
        private TestModel mMdodel;
    
        public  TestPresenter(){
            mMdodel=new TestModel();
        }
        public void getData(){
            mMdodel.getDataModel().subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    getView().get().loadingView(s);
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    getView().get().loadingView("加载失败");
                }
            });
        }
    }
    
    

    以上是个人实践的MVP框架,可能还存在问题,欢迎指教,争取以后改正,谢谢。
    完整的代码请看:https://github.com/huang1xiaoxin/MVPTest

    参考链接:Android MVP模式简单使用和封装使用

    相关文章

      网友评论

          本文标题:Android中使用MVP的简单例子

          本文链接:https://www.haomeiwen.com/subject/lbiqrktx.html