分分钟理解什么叫MVP模式

分分钟理解什么叫MVP模式

MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。
在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,及View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。
这里写图片描述

我们直接看代码:

我们把可视化组件统一当成View,这里面把Activity,Fragment也归类为View层:
MainActivity:

package com.kakasure.mvpdemo.v;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.kakasure.mvpdemo.R;
import com.kakasure.mvpdemo.callback.ActivityCallback;
import com.kakasure.mvpdemo.p.MainPersenter;

/**
 * @author dashentao
 * @date 2015 9-21
 */
public class MainActivity extends AppCompatActivity implements ActivityCallback {
    private Button button;
    private TextView textview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button1);
        textview = (TextView) findViewById(R.id.textview1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainPersenter.getInstance().Opreation1(MainActivity.this);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void toUI(int action, Object object) {
        switch (action) {
            case MainPersenter.ACTION_1:
                if (object != null) {
                    textview.setText((String) object);
                }
                break;
            default:
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        MainPersenter.getInstance().destoryInstance();
    }
}

P层负责请求的封装与结果的回调:

package com.kakasure.mvpdemo.p;

import android.graphics.AvoidXfermode;
import android.os.Message;

import com.kakasure.mvpdemo.callback.ActivityCallback;
import com.kakasure.mvpdemo.m.Model;

import java.util.AbstractCollection;

/**
 * Created by Administrator on 2015/9/21.
 */
public class MainPersenter extends BasePersenter {
    private static MainPersenter persenter;
    private static Object object = new Object();

    public static MainPersenter getInstance() {
        if (persenter == null) {
            synchronized (object) {
                if (persenter == null) {
                    persenter = new MainPersenter();
                }
            }
        }
        return persenter;
    }

    /**
     * 操作
     */
    public void Opreation1(ActivityCallback activityCallback) {
        mActivityCallback = activityCallback;
        Model model = new Model();
        String result = model.test1();
        Message message = Message.obtain();
        message.what = ACTION_1;
        message.obj = result;
        sendMsg(message);
    }

    @Override
    public void destoryInstance() {
        if (persenter != null) {
            persenter = null;
            object = null;
        }
    }
}

核心的回调功能具体由BaseP统一负责:

package com.kakasure.mvpdemo.p;


import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.kakasure.mvpdemo.callback.ActivityCallback;

/**
 * Created by Administrator on 2015/9/21.
 */
public abstract class BasePersenter {
    protected ActivityCallback mActivityCallback;
    /**
     * 动作唯一绑定标志
     */
    public static final int ACTION_1 = 1;

    private void toUI(Message msg) {
        if (mActivityCallback != null) {
            mActivityCallback.toUI(msg.what, msg.obj);
        }
    }

    private Handler myHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            toUI(msg);
        }
    };

    protected void sendMsg(Message message) {
        myHandler.sendMessage(message);
    }

    /**
     * 调用实例销毁时同步销毁Persenter实例,避免单例长期被持有,导致潜在的内存泄露
     */
    public abstract void destoryInstance();
}

Model层:
主要负责数据的组合

package com.kakasure.mvpdemo.m;

/**
 * Created by Administrator on 2015/9/21.
 */
public class Model {
    public Model() {}

    public String test1() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 10; i++) {
            sb.append(i + "");
        }
        return sb.toString();
    }
}

回调接口(非常重要):

package com.kakasure.mvpdemo.callback;

import android.animation.ObjectAnimator;

/**
 * Created by Administrator on 2015/9/21.
 */
public interface ActivityCallback {
    /**
     * return to UI<br/>
     *
     * @param action
     * @param object
     */
    void toUI(int action, Object object);
}

BaseP会通过由操作实例注册进来的callback进行数据分发:

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainPersenter.getInstance().Opreation1(MainActivity.this);
            }
        });
 /**
     * 操作
     */
    public void Opreation1(ActivityCallback activityCallback) {
        mActivityCallback = activityCallback;
        Model model = new Model();
        String result = model.test1();
        Message message = Message.obtain();
        message.what = ACTION_1;
        message.obj = result;
        sendMsg(message);
    }
private void toUI(Message msg) {
        if (mActivityCallback != null) {
            mActivityCallback.toUI(msg.what, msg.obj);
        }
    }

    private Handler myHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            toUI(msg);
        }
    };

    protected void sendMsg(Message message) {
        myHandler.sendMessage(message);
    }

最后数据的返回结果丢给调用实例进行处理:
这样View层根本不需要关心数据的组装过程,只关心结果,从而达到功能解耦。

 @Override
    public void toUI(int action, Object object) {
        switch (action) {
            case MainPersenter.ACTION_1:
                if (object != null) {
                    textview.setText((String) object);
                }
                break;
            default:
                break;
        }
    }

有几点需要特别注意:
1:请求动作的Action标志做唯一化,这样容易管理,并且功能区分明显;

public abstract class BasePersenter {
    protected ActivityCallback mActivityCallback;
    /**
     * 动作唯一绑定标志
     */
    public static final int ACTION_1 = 1;

2 : 当Activity销毁不用时尽量调用destoryInstance释放单例实例,避免长期持有,造成潜在的内存泄露:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        MainPersenter.getInstance().destoryInstance();
    }
}

这里只是抛砖引玉,具体的封装自己可以随便玩,哈哈

github代码链接:https://github.com/dashentao1989/MvpDemo

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值