一、首先介紹什麼是MVP?
MVP是模型(Model)、視圖(View)、主持人(Presenter)的縮寫,分別代表三個模塊。
模型(Model):負責處理數據的加載或者存儲,例如網絡或本地數據庫數據的獲取等等;
視圖(View):負責界面數據的展示,與用戶進行交流;
二、MVP的模塊之間交互
如下圖所示:View和Model不會直接去交互,而是通過Presenter作爲View和Model的橋樑,其中Presenter中同時持有View層以及Model層的Interface的引用,而View層持有Presenter層的Interface引用。當View層某個界面需要展示某些數據時,首先會調用Presenter層的接口,然後Presenter層會調用Model層進行數據請求操作,當Model層的數據請求完成的時候就會調用Presenter層的回調方法通知Presenter層數據加載完成,最後由Presenter層再調用View層的接口將加載的數據顯示在界面上展示給用戶。這就是MVP模式的核心過程。
三、MVP的優缺點:
優點:1、View和Model之間的耦合度降低,使其更關注與自身的業務邏輯,結構清晰維護方便。
2、便於單元測試。
3、代碼複用度提高。
4、代碼框架更適用於快速的迭代開發
缺點:主要爲每一個View都有Presenter,類比較多書寫起來麻煩
四、MVP在Android開發中的使用:
1、我的MVPdemo的源碼目錄結構如下:
bean包下爲:數據類的定義。
Model,Presenter包下各有兩個包,其中的Impl爲對其相應包的業務邏輯的操作。
運行效果如下:
源碼下載:(http://download.csdn.net/detail/qq_30000411/9687960)
該demo爲MVP模式下開發的聊天機器人demo。
2、各個包下的代碼如下:
(1)、bean 包下的JiQiRen類爲數據類的定義
package com.xyliwp.mvpdemo.bean;
/**
* Created by lwp940118 on 2016/11/20.
*/
public class JiQiRen {
private int tag;
private String message;
public int getTag() {
return tag;
}
public void setTag(int tag) {
this.tag = tag;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
(2)、Model層的兩個子包下的文件:
JiQiRenModel爲Model層接口的定義
package com.xyliwp.mvpdemo.Model.Model;
import com.xyliwp.mvpdemo.Model.ModelImpl.JiQiRenModelImpl;
/**
* model層的接口
* Created by lwp940118 on 2016/11/20.
*/
public interface JiQiRenModel {
/**
* 加載數據並且的接口
* @param infor
* @param listener
*/
void loadMessage(String infor, JiQiRenModelImpl.OnLoadMessageListListener listener);
}
JiQiRenModelImpl 爲Model層的業務邏輯。
package com.xyliwp.mvpdemo.Model.ModelImpl;
import android.os.Handler;
import com.xyliwp.mvpdemo.Model.Model.JiQiRenModel;
import com.xyliwp.mvpdemo.bean.JiQiRen;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Created by lwp940118 on 2016/11/20.
*/
public class JiQiRenModelImpl implements JiQiRenModel{
public static final String api = "http://www.tuling123.com/openapi/api";
public static final String key = "959060c92fb845acb8d9073934355364";
public static final String url = api+"?key="+key+"&info=";
private Handler handler = null;
@Override
public void loadMessage(final String infor, final OnLoadMessageListListener listener) {
handler = new Handler(){
@Override
public void handleMessage(android.os.Message msg) {
JiQiRen message = (JiQiRen) msg.obj;
if (message.getTag() == 1){
listener.onSuccess(message);
}else{
listener.onFailure(message);
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient okHttpClient = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
builder.add("json","true");
RequestBody body = builder.build();
Request request = new Request.Builder()
.url(url+infor)
.post(body)
.build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.isSuccessful()){
JSONObject jsonObject = new JSONObject(response.body().string());
JiQiRen message = new JiQiRen();
message.setMessage(jsonObject.toString());
message.setTag(1);
android.os.Message message1 = new android.os.Message();
message1.obj = message;
handler.sendMessage(message1);
}else {
JiQiRen message = new JiQiRen();
message.setMessage("小鳳異常,小鳳異常,小鳳異常,重要的事情說三邊");
message.setTag(0);
android.os.Message message1 = new android.os.Message();
message1.obj = message;
handler.sendMessage(message1);
}
} catch (IOException e) {
e.printStackTrace();
}catch (JSONException e){
e.printStackTrace();
}
}
}).start();
}
public interface OnLoadMessageListListener{
void onSuccess(JiQiRen message);
void onFailure(JiQiRen message);
}
}
(3)、Presenter層兩個子包下的文件
JiQiRenPresenter爲Presenter層的接口
這裏寫代package com.xyliwp.mvpdemo.Presenter.Presenter;
/**
* Created by lwp940118 on 2016/11/20.
*/
public interface JiQiRenPresenter {
/**
* 添加消息的message
* @param message
*/
void loadMessage(String message);
}
JiQiRenPresenterImpl爲Presenter層的Model層調用以及View層的數據展示。
package com.xyliwp.mvpdemo.Presenter.PresenterImpl;
import com.xyliwp.mvpdemo.Model.Model.JiQiRenModel;
import com.xyliwp.mvpdemo.Model.ModelImpl.JiQiRenModelImpl;
import com.xyliwp.mvpdemo.Presenter.Presenter.JiQiRenPresenter;
import com.xyliwp.mvpdemo.View.JiQiRenView;
import com.xyliwp.mvpdemo.bean.JiQiRen;
/**
* Created by lwp940118 on 2016/11/20.
*/
public class JiQiRenPresenterImpl implements JiQiRenPresenter,JiQiRenModelImpl.OnLoadMessageListListener{
private JiQiRenView jiQiRenView;
private JiQiRenModel messageModel;
public JiQiRenPresenterImpl(JiQiRenView jiQiRenView){
this.jiQiRenView = jiQiRenView;
this.messageModel = new JiQiRenModelImpl();
}
@Override
public void onSuccess(JiQiRen message) {
jiQiRenView.addMessage(message);
}
@Override
public void loadMessage(String message) {
messageModel.loadMessage(message,this);
}
@Override
public void onFailure(JiQiRen message) {
jiQiRenView.showMessageFailure(message);
}
}
(4)、View層的接口文件
package com.xyliwp.mvpdemo.View;
import com.xyliwp.mvpdemo.bean.JiQiRen;
/**
* 機器人的view
* Created by lwp940118 on 2016/11/20.
*/
public interface JiQiRenView {
/**
* 信息添加成功 展示給接界面
* @param jiQiRen
*/
void addMessage(JiQiRen jiQiRen);
/**
* 添加失敗 將失敗展示給界面
* @param jiQiRen
*/
void showMessageFailure(JiQiRen jiQiRen);
}
(5)、MVP模式在Android中Activity的調用,向Presenter發送數據請求,和Presenter返回數據顯示。
package com.xyliwp.mvpdemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.xyliwp.mvpdemo.Presenter.Presenter.JiQiRenPresenter;
import com.xyliwp.mvpdemo.Presenter.PresenterImpl.JiQiRenPresenterImpl;
import com.xyliwp.mvpdemo.View.JiQiRenView;
import com.xyliwp.mvpdemo.bean.JiQiRen;
public class MainActivity extends AppCompatActivity implements JiQiRenView{
private TextView textView;
private EditText editText;
private Button button;
private JiQiRenPresenter messagePresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
messagePresenter = new JiQiRenPresenterImpl(this);
initView();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
messagePresenter.loadMessage(editText.getText().toString());
}
});
}
private void initView(){
textView = (TextView)findViewById(R.id.textview);
editText = (EditText)findViewById(R.id.edittext);
button = (Button)findViewById(R.id.button);
}
@Override
public void addMessage(JiQiRen message) {
String s = message.getMessage();
textView.setText(s);
}
@Override
public void showMessageFailure(JiQiRen message) {
textView.setText(message.getMessage());
}
}
xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="80dp"
android:id="@+id/edittext"/>
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="300dp" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="button"/>
</LinearLayout>
讀者可自行結合MVC開發框架來對比理解MVP開發框架