【android学习】MVP学习

mvp与mvc得区别

【android学习】MVP学习_第1张图片

上面这张图是网上找的,可以明显得区别MVP和MVC

我们先看一下MVC

  1. 模型层(model):相当于我们得网络请求
  2. 视图层(view):相当于我们得布局文件
  3. 控制层(controller):相当于我们得activity

相当于我们得activity即要和我们得布局文件打交道,又要和我们得数据层打交道,使得我们得activity就会有相当多得代码,可读性降低,而MVP得出现,就刚好弥补了这一点

我们在看一下MVP

  1. 模型层(model):相当于我们得网络请求
  2. 视图层(view):相当于我们得布局文件
  3. 链接层(presenter):讲model 与 view层进行链接
  4. 不严格意义上讲,也可以说还有一个controller层,就是我们得activity,只是现在得activity只是用来继承view,实现view得展示

我们先来实现一个mvp结构

先看我们得M层,就一个接口,用来给activity提供网络加载出来得数据

public interface MainView extends IBaseView {
    //显示图片(回调函数)
    void showGirlView(List girls);
}

再看看model层,这里我们模仿从网络上加载图片

public class MainModel {

    public List loadData() {
        List data = new ArrayList<>();
        data.add(new Girl(R.drawable.f1, "一星", "****"));
        data.add(new Girl(R.drawable.f2, "一星", "****"));
        data.add(new Girl(R.drawable.f3, "一星", "****"));
        data.add(new Girl(R.drawable.f4, "一星", "****"));
        data.add(new Girl(R.drawable.f5, "一星", "****"));
        data.add(new Girl(R.drawable.f6, "一星", "****"));
        data.add(new Girl(R.drawable.f7, "一星", "****"));
        data.add(new Girl(R.drawable.f8, "一星", "****"));
        data.add(new Girl(R.drawable.f9, "一星", "****"));
        data.add(new Girl(R.drawable.f10, "一星", "****"));
        return data;
    }
}

再看看presenter层,在这里,我们通过view得showGirlView方法,将MainModel得到得数据,和MainView中的接口进行绑定

public class MainPresenter extends BasePresenter  {

    MainModel mainModel = new MainModel();

    public void loadData(){
        iMainView.get().showGirlView(mainModel.loadData());
    }

}

然后就是我们得activity层,activity层继承MainView以后,就可以通过showGirlView方法得到刚才MainModel 加载得数据

public class MainActivity extends BaseActivity,MainView> implements MainView{

    @Override
    public void showGirlView(List girls) {
        //表示层就会把数据填到girls上
        listView.setAdapter(new GirlAdapter(this, girls));
    }

}

就这样,我们在mainactivity中就可以得到网络加载得数据了,这里我为了体现MVP得结构,并没有贴出所有得代码,完整代码下载地址demo下载

 

mvp得改良

我们发现在presenter层里面,我们将model层得到得数据,再一次得传递给了view层,我们可不可以直接将这一次解耦呢

iMainView.get().showGirlView(mainModel.loadData());

下面就是改良得方案,类似RXBus得方式,在model层得到数据,我们就通过单独得通道,分发出去,在想要这个数据得地方,注册接受呢

首先我们戴良model得数据加载,将得到得数据,放入通道里面

public class MainModel {

    public void loadData() {
        RxBusUtils.getInstance().chainProcess(new Function() {
            @Override
            public Object apply(Object o) throws Exception {
                List data = new ArrayList<>();
                data.add(new Girl(R.drawable.f1, "一星", "****"));
                data.add(new Girl(R.drawable.f2, "一星", "****"));
                data.add(new Girl(R.drawable.f3, "一星", "****"));
                data.add(new Girl(R.drawable.f4, "一星", "****"));
                data.add(new Girl(R.drawable.f5, "一星", "****"));
                data.add(new Girl(R.drawable.f6, "一星", "****"));
                data.add(new Girl(R.drawable.f7, "一星", "****"));
                data.add(new Girl(R.drawable.f8, "一星", "****"));
                data.add(new Girl(R.drawable.f9, "一星", "****"));
                data.add(new Girl(R.drawable.f10, "一星", "****"));
                return data;
            }
        });
    }
}
  • 如果我们这里注册是在presenter里面
RxBusUtils.getInstance().register(presenter);

 就只需要在presenter里面通过调用这个方法,就可以得到model中得数据,并传递给view层

    @RegisterRxBusUtils
    public void getShowGirlsData(ArrayList girls) {
    
        iBaseView.get().showGirlView(girls);
    }
  • 如果我们将注册放在activity里面
RxBusUtils.getInstance().register(MainActiviy.this);

 在activity中,就可以直接通过这个方法,得到model中得数据

   @RegisterRxBusUtils
    public void getShowGirlsData(ArrayList girls) {
     
        listView.setAdapter(new GirlAdapter(this, girls));

    }

这样,就可以解耦presenter和view层了

 

我这里贴出RxBusUtils 中得方法,提供大家学习

public class RxBusUtils {

    private static final String TAG = "RxBusUtils";
    //订阅者集合
    private Set subscribers;
    /**
     * 注册
     */
    public synchronized void register(Object subscriber){
        subscribers.add(subscriber);
    }
    /**
     * 取消注册
     */
    public synchronized void unRegister(Object subscriber){
        subscribers.remove(subscriber);
    }


    //volatile 自带线程安全(禁止指令重排)
    private static volatile  RxBusUtils instance;

    private RxBusUtils(){
        //读写分离的集合
        subscribers=new CopyOnWriteArraySet<>();
    }

    public static  synchronized  RxBusUtils  getInstance(){
        if (null==instance){
            synchronized (RxBusUtils.class){
                if (null==instance){
                    instance = new RxBusUtils();
                }
            }
        }
        return  instance;
    }



    /**
     * 把处理过程包装起来
     * function:就是用户的操作
     */
    public void chainProcess(Function function){

        Observable.just("")
                .subscribeOn(Schedulers.io())
                .map(function)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Object data) throws Exception {
                        if (data == null){
                            return;
                        }
                        send(data);
                    }
                });
    }


    public void send(Object data){
        for (Object subscriber : subscribers) {
            //扫描注解,将数据发送到注册的对象标记的位置(一个方法)
            //subscriber表示层
            callMethodByAnnotation(subscriber,data);
        }
    }


    private void callMethodByAnnotation(Object target, Object data) {
        //1.得到presenter中写的所有的方法
        Method[] methodArray = target.getClass().getDeclaredMethods();
        //2.如果哪个方法上用了我们写的注解,就把数据输入
        for (Method method : methodArray) {
            Log.d(TAG,"--"+method.getName());
            if (null!=method.getAnnotation(RegisterRxBusUtils.class)){
                Class[] parameterTypes = method.getParameterTypes();
                for (Class parameterType : parameterTypes) {
                    Log.d(TAG,parameterType.getName());
                }
                Class paramType = parameterTypes[0];
                if (data.getClass().getName().equals(paramType.getName())){
                    try {
                        method.invoke(target,new Object[]{data});
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }
} 
  

上面得方式,是以RXBus通道方式,提供学习使用 修改后得demo下载

你可能感兴趣的:(android学习)