淺談MVP模式(開發Android聊天機器人)

一、首先介紹什麼是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層的兩個子包下的文件

JiQiRenModelModel層接口的定義

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);
}

JiQiRenModelImplModel層的業務邏輯

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開發框架

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章