MVP模式 概念就不說了,大家都懂。View層通過Persenter層相互通信,避免了View中大量的業務代碼,而將其提取到Model中。其實簡單的來說,就是通過介面回調,把業務分離出去。提高代碼的可讀性和已維護性。 直接看案例就明白了。 案例(用戶登錄) 常規的用戶登錄寫法就是Activity(f ...
MVP模式
概念就不說了,大家都懂。View層通過Persenter層相互通信,避免了View中大量的業務代碼,而將其提取到Model中。其實簡單的來說,就是通過介面回調,把業務分離出去。提高代碼的可讀性和已維護性。
直接看案例就明白了。
-----------------------------
案例(用戶登錄)
常規的用戶登錄寫法就是Activity(fragment)中獲取用戶名密碼,網路請求登錄介面,返回是否登錄成功
而MVP的模式就是,要把網路請求這一部分單獨提取出來放到model層裡面,View層也就是我們的Activity只寫頁面相關的操作,
- 創建LoginModel如下:
package com.cyq.mvppractice.model;
public class LoginModel {
public static boolean login(String username, String password) {
//一般是請求網路介面咯
//具體邏輯我就不寫了,這裡模擬一下,直接返回登錄成功
return true;
}
}
很簡單,就是一個常規類和常規操作而已,處理具體的登錄網路請求
- 定義一個介面LoginInterface和LoginPersenter類
LoginInterface中又定義了兩個介面,View和Persenter分別繼承這兩個介面,實現View和Persenter層的交互,具體如下
package com.cyq.mvppractice.contract;
public interface LoginInterface {
/**
* View層需要繼承這個介面,通過介面方法View層獲取返回結果
*/
interface View {
//判斷是否登錄成功
void isLogin(boolean islogin);
}
/**
* persenter需要繼承的介面,通過介面方法傳入View層的值
*/
interface Persenter {
//model層需要哪些傳入數據從這個介面傳入
void goLogin(String username, String password);
}
}
LoginPersenter.class
package com.cyq.mvppractice.persenter;
import com.cyq.mvppractice.contract.LoginInterface;
import com.cyq.mvppractice.model.LoginModel;
public class LoginPersenter implements LoginInterface.Persenter {
//通過構造方法傳入view,相當於傳入了activity和fragment
private LoginInterface.View view;
public LoginPersenter(LoginInterface.View view) {
this.view = view;
}
/**
* 調用model層業務,最終通過view.isLogin(b),通知view層獲取數據
*
* @param username
* @param password
*/
@Override
public void goLogin(String username, String password) {
boolean isLogin = LoginModel.login(username, password);
//回調通知View層
view.isLogin(isLogin);
}
}
最後在View中繼承LoginInterface.View介面,實例化LoginInterface.Persenter介面
package com.cyq.mvppractice;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.cyq.mvppractice.contract.LoginInterface;
import com.cyq.mvppractice.persenter.LoginPersenter;
public class LoginActivity extends AppCompatActivity implements LoginInterface.View {
private LoginInterface.Persenter mPersenter;
private EditText usernameEt, passwordEt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mPersenter = new LoginPersenter(this);
usernameEt = findViewById(R.id.et_username);
passwordEt = findViewById(R.id.et_password);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String usernameStr = usernameEt.getText().toString();
String passwordStr = passwordEt.getText().toString();
if ((!TextUtils.isEmpty(usernameStr)) && (!TextUtils.isEmpty(passwordStr)))
mPersenter.goLogin(usernameStr, passwordStr);
else {
Toast.makeText(LoginActivity.this, "請輸入用戶名或密碼", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public void isLogin(boolean islogin) {
if (islogin) {
Toast.makeText(LoginActivity.this, "登錄成功", Toast.LENGTH_SHORT).show();
}
}
}
- 就這麼簡單,把網路請求資料庫操作等複雜業務單獨放到model層中處理,通過介面回調獲得model處理結果返回到View層,也就避免了在View層編寫大量的業務邏輯了
- Xml佈局如下,就是兩個Edittext和一個登陸按鈕
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp"
tools:context=".LoginActivity">
<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入用戶名" />
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="請輸入密碼" />
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="登錄" />
</LinearLayout>
- 沒看懂?再認真看一遍,再寫個小demo就ok了,主要是理解其思想