編輯:關於Android編程
說來慚愧,MVP的架構模式已經在Android領域出現一兩年了,但是到今天自己才開始Android領域中的MVP架構征程。閒話不多說,開始吧!
我記得我找第一份工作時,面試官問我“android是否屬於MVC架構模式,簡述一下”。確實,Android的整體設計結構就是MVC的設計模式,在J2EE的開發中,使用的也是MVC模式,MVC模式是一個經典,經歷了幾十年的考驗。Android項目中的MVC架構:
View:是應用程序中處理數據顯示的部分,對應於layout文件下的布局文件 Model:業務邏輯和實體模型 Controllor:是應用程序中處理用戶交互的部分,Activity來充當。看似分工明確,但是也給我們帶來了不少問題,如果一個頁面的業務邏輯非常復雜,我們的Activty需要大量的邏輯處理代碼,使得Activity既像View又像Controllor,又當爹又當媽,工作量非常大。造成代碼的閱讀星非常差。
為了解決這個問題,MVP模式就在Android領域誕生了。補充:我查看資料發現MVP模式最早是微軟設計出來的,應用在Visual Stuido平台,不得不說微軟雖然閉源,但是很niubility。
上面的圖,精煉的概述了MVP架構之間的通訊流程,在android中。
模型(Model):業務邏輯處理,負責處理數據的加載或者存儲,比如從網絡或本地數據庫獲取數據等;視圖(View):負責界面數據的展示,與用戶進行交互,就是Activity;主導器(Presenter):相當於協調者,是模型與視圖之間的橋梁,將模型與視圖分離開來。通過Presenter進行它們之間的交互,隔離了M、V之間的直接交互。這樣的架構,就讓我們的Activity更像View,降低了M、V之間的耦合度。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMyBpZD0="三mvp實踐">三、MVP實踐
我們先看下我們的效果圖:
這是一個簡答的登陸頁面,在這個登陸頁面中,我們就觸發一個事件,就是點擊登陸事件。我們先看看我們的工程組織架構。
我們分別創建了:bean、model、presenter、view四個包,為了解放Activity,我們把以前Activity裡的大量邏輯進行拆分。
我們創建實體UserBean,用來存放我們的用戶信息,這個沒什麼說的。
public class UserBean implements Parcelable{
private String name;
private String password;
public UserBean(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(password);
}
}
我們首先從View(視圖層)看,view包下存放了我們視圖層中的操作,它不涉及任何業務邏輯,主要是針對我們的頁面進行數據的獲取與設置。我們針對這個登陸功能,進行分析:
姓名和密碼的獲取姓名和密碼的保存我們抽取出頁面View層需要做的事情,接下來我們定義一個IUserView接口,裡面包含我們抽取出來的方法。
/**
* 抽離View層,用於View頁面的數據獲取之類
* @author Administrator
*
*/
public interface IUserView {
public String getUserName();
public String getUserPsd();
}
我們只進行了獲取,沒有做保存。總結:View層的任務就是抽象頁面的數據,提取出來寫成方法。
在view層,我們的數據獲取有了著落,現在我們就開始處理我們的業務邏輯。根據頁面得知,我們就模擬一個登陸功能,所以它就一個登陸事件。我們創建IUserModel接口用於包含我們處理的業務邏輯。
/**
* 業務邏輯處理
* @author Administrator
*
*/
public interface IUserModel {
/**
*提取的一個登陸方法,當然還可以有其它方法,比如獲取數據,保存用戶信息之類
* @param name 用戶名
* @param pwd 密碼
* @param loginListener 登陸監聽
*/
public void login(String name,String pwd,ILoginListener loginListener);
}
有了業務邏輯的接口規范,我們還需要去實現它,給與我們想要的邏輯。所以就有了UserModel類:
public class UserModel implements IUserModel{
@Override
public void login(String name, String pwd, ILoginListener loginListener) {
if(TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd)){
loginListener.onError();
return;
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if("dsw".equals(name) && "123".equals(pwd)){
loginListener.onSucess();
}else{
loginListener.onFail();
}
}
}
我們為了方便我們對業務邏輯處理的監聽,所以我們創建了一個接口,用來判斷我們的登陸事件。
/**
* 登陸接口的監聽,方便我們在View層中控制,便於給出提示
* @author Administrator
*
*/
public interface ILoginListener {
//登陸成功
public void onSucess();
//登陸失敗
public void onFail();
//數據不完成
public void onError();
}
我們用來監聽業務處理的判斷,比如成功了我們彈出一個Toast之類的。
數據有了,對數據的業務處理也有了,這裡我們的Presenter就閃靈登場了。記住是Presenter、Presenter、Presenter(重要的東西說三次)。它用來連接我們的M、V層,讓二者打通任督二脈實現整個流程。所以為了實現二者的聯系,它的內部必然會有M、V的實例。來看看IUserPresenter:
public class IUserPresenter {
//數據源
private IUserView userView;
//處理業務邏輯
private IUserModel userModel;
public IUserPresenter(IUserView userView){
this.userView = userView;
userModel = new UserModel();
}
/**
* 登陸方法,進行M,V層的關系建立
* @param loginListener
*/
public void login(ILoginListener loginListener){
userModel.login(userView.getUserName(), userView.getUserPsd(), loginListener);
}
}
我們只需要在Activity中創建一個IUserPresenter類,然後調用login方法進行登錄即可。在這段代碼中,IUserView是我們的數據源,我們通過它的方法用於從頁面獲取數據,所以我們的Activity必須實現這個IUserView接口,然後傳遞給IUserPresenter。在IUserPresenter中調用IUserModel的實現業務邏輯的處理。
public class MainActivity extends Activity implements IUserView {
private EditText et_name,et_pwd;
private Button btn_login;
//指示器與View層進行交互
private IUserPresenter userPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name = (EditText) findViewById(R.id.et_name);
et_pwd = (EditText) findViewById(R.id.et_psw);
btn_login = (Button) findViewById(R.id.btn_login);
userPresenter = new IUserPresenter(this);
btn_login.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
userPresenter.login(loginListener);
}
});
}
@Override
public String getUserName() {
return et_name.getText().toString();
}
@Override
public String getUserPsd() {
return et_pwd.getText().toString();
}
/**
* 登陸監聽接口
*/
private ILoginListener loginListener = new ILoginListener() {
@Override
public void onSucess() {
Toast.makeText(getApplication(), "登陸成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onFail() {
Toast.makeText(getApplication(), "登陸失敗", Toast.LENGTH_SHORT).show();
}
@Override
public void onError() {
Toast.makeText(getApplication(), "數據不完整,請重新輸入", Toast.LENGTH_SHORT).show();
}
};
}
在activity中,我們實現IUserView接口,來實現該view層的數據獲取。然後創建IUserPresenter類,調用login方法進行登錄。同時實現對業務邏輯的處理監聽。
至此,我們就完成了整個的流程,看看我們的效果圖:
源碼本來打算上傳的熬csdn的,結果上傳不了,所以果斷github
強烈建議大家手動敲一遍代碼,加深理解。
先看一下效果圖支持本地圖片以及網絡圖片or本地網絡混合。使用方式:<com.jalen.autobanner.BannerView android:id=@+id/
最近,由於正在做的一個應用中要用到側滑菜單,所以通過查資料看視頻,學習了一下自定義View,實現一個類似於QQ的側滑菜單,順便還將其封裝為自定義組件,可以實現類似QQ的側
launchmode的四種模式,不需要細說:standard、singleTop、singleTask、singleInstance。 此博客關注的是,關於Act
這篇介紹第二種自定義View方法,創建復合控件。創建復合控件創建復合控件可以很好地創建出具有重用功能的控件集合。這種方式通常需要繼承一個合適的ViewGroup,再給它添