Android中使用MVP的简单例子

2020-08-03  本文已影响0人  132xin

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模式简单使用和封装使用

上一篇 下一篇

猜你喜欢

热点阅读