Android MVP模式實(shí)戰(zhàn)教程
一、什么是MVP
在網(wǎng)上找了些資料,整理如下:
MVP是模型(Model)、視圖(View)、主持人(Presenter)的縮寫(xiě),分別代表項(xiàng)目中3個(gè)不同的模塊。
模型(Model):負(fù)責(zé)處理數(shù)據(jù)的加載或者存儲(chǔ),比如從網(wǎng)絡(luò)或本地?cái)?shù)據(jù)庫(kù)獲取數(shù)據(jù)等;
視圖(View):負(fù)責(zé)界面數(shù)據(jù)的展示,與用戶(hù)進(jìn)行交互;
主持人(Presenter):相當(dāng)于協(xié)調(diào)者,是模型與視圖之間的橋梁,將模型與視圖分離開(kāi)來(lái)。
如下圖所示,View與Model并不直接交互,而是使用Presenter作為View與Model之間的橋梁。其中Presenter中同時(shí)持有Viwe層以及Model層的Interface的引用,而View層持有Presenter層Interface的引用。當(dāng)View層某個(gè)界面需要展示某些數(shù)據(jù)的時(shí)候,首先會(huì)調(diào)用Presenter層的某個(gè)接口,然后Presenter層會(huì)調(diào)用Model層請(qǐng)求數(shù)據(jù),當(dāng)Model層數(shù)據(jù)加載成功之后會(huì)調(diào)用Presenter層的回調(diào)方法通知Presenter層數(shù)據(jù)加載完畢,最后Presenter層再調(diào)用View層的接口將加載后的數(shù)據(jù)展示給用戶(hù)。這就是MVP模式的整個(gè)核心過(guò)程。

在MVP模式里通常包含4個(gè)要素:
(1)View:負(fù)責(zé)繪制UI元素、與用戶(hù)進(jìn)行交互(在Android中體現(xiàn)為Activity);
(2)View interface:需要View實(shí)現(xiàn)的接口,View通過(guò)View interface與Presenter進(jìn)行交互,降低耦合,方便進(jìn)行單元測(cè)試;
(3)Model:負(fù)責(zé)存儲(chǔ)、檢索、操縱數(shù)據(jù)(有時(shí)也實(shí)現(xiàn)一個(gè)Model interface用來(lái)降低耦合);
(4)Presenter:作為View與Model交互的中間紐帶,處理與用戶(hù)交互的負(fù)責(zé)邏輯。

二、MVP模式的使用

上面一張簡(jiǎn)單的MVP模式的UML圖,從圖中可以看出,使用MVP,至少需要經(jīng)歷以下步驟:
1.創(chuàng)建IPresenter接口,把所有業(yè)務(wù)邏輯的接口都放在這里,并創(chuàng)建它的實(shí)現(xiàn)PresenterCompl(在這里可以方便地查看業(yè)務(wù)功能,由于接口可以有多種實(shí)現(xiàn)所以也方便寫(xiě)單元測(cè)試)
2.創(chuàng)建IView接口,把所有視圖邏輯的接口都放在這里,其實(shí)現(xiàn)類(lèi)是當(dāng)前的Activity/Fragment
3.由UML圖可以看出,Activity里包含了一個(gè)IPresenter,而PresenterCompl里又包含了一個(gè)IView并且依賴(lài)了Model。Activity里只保留對(duì)IPresenter的調(diào)用,其它工作全部留到PresenterCompl中實(shí)現(xiàn)
4.Model并不是必須有的,但是一定會(huì)有View和Presenter
三、一個(gè)簡(jiǎn)單的MVP示例
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的用戶(hù)登錄
效果如下:

先來(lái)看看java文件的目錄結(jié)構(gòu):

1.Baen包
UserBean
package com.example.mvpe.bean;
/**
* Created by fendo on 2017/4/29.
*/
public class UserBean {
private String username;
private String userpwd;
public UserBean() {
}
public UserBean(String username, String userpwd) {
this.username = username;
this.userpwd = userpwd;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpwd() {
return userpwd;
}
public void setUserpwd(String userpwd) {
this.userpwd = userpwd;
}
}
2.Model包
IUserModel類(lèi)
package com.example.mvpe.model;
import com.example.mvpe.bean.UserBean;
/**
* Created by fendo on 2017/4/29.
*/
public interface IUserModel {
void setSid(int cid);
UserBean load(int sid);
void setUsername(String username);
void setUserpwd(String userpwd);
}
UserModelimp類(lèi)
package com.example.mvpe.model;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
import com.example.mvpe.bean.UserBean;
/**
* Created by fendo on 2017/4/29.
*/
public class UserModelimp implements IUserModel{
private static final String ACTIVITY_TAG="UserModelimp";
private String username;
private String userpwd;
private int sid;
private SparseArray<UserBean> su=new SparseArray<UserBean>();
@Override
public void setSid(int cid) {
sid=cid;
}
@Override
public UserBean load(int sidy) {
sid=sidy;
UserBean ub=su.get(sid,new UserBean("not found",
"not found"));
return ub;
}
@Override
public void setUsername(String usernamey) {
username=usernamey;
}
@Override
public void setUserpwd(String userpwdy) {
userpwd=userpwdy;
UserBean usb=new UserBean(username,userpwd);
System.out.print(username+"----"+userpwd+"----"+sid);
Log.d(UserModelimp.ACTIVITY_TAG, "Start_OK"+username+"----"+userpwd+"----"+sid);
su.append(sid,usb);
}
}
3.persenter包
UserPersenter類(lèi)
package com.example.mvpe.presenter;
import android.util.Log;
import android.view.View;
import com.example.mvpe.bean.UserBean;
import com.example.mvpe.model.IUserModel;
import com.example.mvpe.model.UserModelimp;
import com.example.mvpe.view.IUserView;
/**
* Created by fendo on 2017/4/29.
*/
public class UserPersenter {
private static final String ACTIVITY_TAG="UserPersenter";
private IUserView iUserView;
private IUserModel iUserModel;
public UserPersenter(IUserView view){
iUserView=view;
iUserModel=new UserModelimp();
}
public void saveuser(int sid,String username,String userpwd){
iUserModel.setSid(sid);
iUserModel.setUsername(username);
iUserModel.setUserpwd(userpwd);
}
public void loaduser(int sid){
UserBean usb=iUserModel.load(sid);
Log.d(ACTIVITY_TAG, "loaduser: "+usb.getUsername());
iUserView.setUsername(usb.getUsername());
iUserView.setUserpwd(usb.getUserpwd());
}
}
4.view包
IUserView類(lèi)
package com.example.mvpe.view;
import com.example.mvpe.bean.UserBean;
/**
* Created by fendo on 2017/4/29.
*/
public interface IUserView {
int getID();
void setUsername(String username);
void setUserpwd(String userpwd);
String getUserpwd();
String getUsername();
}
UserActivity類(lèi)
package com.example.mvpe.view;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.example.mvpe.R;
import com.example.mvpe.presenter.UserPersenter;
import android.view.View.OnClickListener;
import android.widget.Toast;
/**
* Created by fendo on 2017/4/29.
*/
public class UserActivity extends Activity implements OnClickListener,IUserView{
private EditText userid;
private EditText username;
private EditText userpwd;
private Button read;
private Button write;
private UserPersenter usp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
usp=new UserPersenter(this);
setContentView(R.layout.activity_main);
findviewbyid();
read.setOnClickListener(this);
write.setOnClickListener(this);
}
public void findviewbyid(){
userid= (EditText) findViewById(R.id.userid);
username= (EditText) findViewById(R.id.usertext);
userpwd= (EditText) findViewById(R.id.userpwd);
read= (Button) findViewById(R.id.read);
write= (Button) findViewById(R.id.write);
}
@Override
public int getID() {
return Integer.parseInt(userid.getText().toString());
}
@Override
public void setUsername(String usernamcc) {
username.setText(usernamcc);
}
@Override
public void setUserpwd(String userpw) {
userpwd.setText(userpw);
}
@Override
public String getUserpwd() {
return userpwd.getText().toString();
}
@Override
public String getUsername() {
return username.getText().toString();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.read :
usp.loaduser(getID());
Toast.makeText(getApplicationContext(), "點(diǎn)擊了讀"+getID(), Toast.LENGTH_SHORT).show();
break;
case R.id.write:
usp.saveuser(getID(),getUsername(),getUserpwd());
Toast.makeText(getApplicationContext(), "點(diǎn)擊了存"+getID()+"--"+getUsername()+"--"+getUserpwd(), Toast.LENGTH_SHORT).show();
break;
}
}
}
可以看到View只負(fù)責(zé)處理與用戶(hù)進(jìn)行交互,并把數(shù)據(jù)相關(guān)的邏輯操作都扔給了Presenter去做。而Presenter調(diào)用Model處理完數(shù)據(jù)之后,再通過(guò)IUserView更新View顯示的信息。
下載:源碼
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android 使用kotlin 實(shí)現(xiàn)點(diǎn)擊更換全局語(yǔ)言(中日英切換)
這篇文章主要介紹了android kotlin 點(diǎn)擊更換全局語(yǔ)言的實(shí)現(xiàn)方法,這里主要介紹中日英切換,需要的朋友可以參考下2019-11-11
Android Webview的postUrl與loadUrl加載頁(yè)面實(shí)例
這篇文章主要介紹了Android Webview的postUrl與loadUrl加載頁(yè)面實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
Android實(shí)現(xiàn)檢測(cè)實(shí)體按鍵事件并屏蔽
這篇文章主要介紹了Android實(shí)現(xiàn)檢測(cè)實(shí)體按鍵事件并屏蔽 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Android 自定義縮短Toast顯示時(shí)間的實(shí)例代碼
這篇文章主要介紹了Android 自定義縮短Toast顯示時(shí)間,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
Android使用AnimationDrawable實(shí)現(xiàn)閃爍紅光動(dòng)畫(huà)效果(案例詳解)
這篇文章主要介紹了Android使用AnimationDrawable實(shí)現(xiàn)閃爍紅光動(dòng)畫(huà)效果,實(shí)現(xiàn)閃爍紅光效果可以使用Android中的Animation和Drawable資源,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
簡(jiǎn)單實(shí)現(xiàn)android短信發(fā)送器
這篇文章主要為大家詳細(xì)介紹了如何簡(jiǎn)單實(shí)現(xiàn)android短信發(fā)送器 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android SeekBar實(shí)現(xiàn)平滑滾動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android SeekBar實(shí)現(xiàn)平滑滾動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03

