日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android MVP——mvp架构的应用和优化

發布時間:2023/12/8 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android MVP——mvp架构的应用和优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MVP架構在android還是很好用的。我也在試著將mvp用在項目中。

下面我就來說說mvp模式的應用和優化。

mvp模式的概念

MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示。

比較

mvc:

1,在MVC里,View是可以直接訪問Model的,View里會包含Model信息,不可避免的還要包括一些業務邏輯。
2,Model不依賴于View,但是View是依賴于Model。
3,有一些業務邏輯在View里實現了,導致要更改View也是比較困難的,至少那些業務邏輯是無法重用的。

mvp:

1,在MVP里,Presenter完全把Model和View進行了分離,主要的程序邏輯在Presenter里實現。
2,Presenter與具體的View是沒有直接關聯的,而是通過定義好的接口進行交互。從而使得在變更View時候可以保持Presenter的不變,即重用
3,應用程序的邏輯主要在Presenter來實現,其中的View是很薄的一層。這樣一來就編寫測試用的View,模擬用戶的各種操作,從而實現對Presenter的測試

mvp的系統設計

我們先來個mvp系統的設計。(我們在這里模仿一個登陸的請求)
概要設計圖

1,mobel層

mobel接口:規定操作數據的接口。

接口:IUserLoginMobel

/*** 用戶操作接口 Model 業務層接口*/ public interface IUserLoginMobel{/*** 用戶登錄** @param name* @param pwd* @param loginListener*/void login(String name, String pwd, OnLoginListener loginListener); }

登錄狀態回調接口:

/*** 登陸狀態接口*/ public interface OnLoginListener {void loginSuccess(UserInfoBean user);void loginFailed(String message); }

類:用戶登陸操作類 UserLoginModel

/*** 用戶登陸操作類,Model 業務層(接收數據,處理出局)*/ public class UserLoginModel implements IUserLoginMobel {@Overridepublic void login(final String name, final String pwd, final OnLoginListener loginListener) {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(2000);if ("admin".equals(name) && "admin".equals(pwd)) {UserInfoBean userInfoBean = new UserInfoBean();userInfoBean.setUserId(System.currentTimeMillis());userInfoBean.setUserName(name);userInfoBean.setUserPwd(pwd);loginListener.loginSuccess(userInfoBean);} else {loginListener.loginFailed("密碼錯誤");}} catch (InterruptedException e) {e.printStackTrace();}}}).start();} }

2,Presenter層

定義 UserLoginPresenter類

/*** 用戶登錄的任命者。Presenter (用于接收模型發出的結果,給view層發送命令)*/ public class UserLoginPresenter {protected IUserLoginView mvcView;//view的接口private IUserLoginMobel userLoginMobel;//mobel的接口private Handler mHandler = new Handler();public UserLoginPresenter(IUserLoginView userLoginView) {this.mvcView = userLoginView;this.userLoginMobel = new UserLoginModel();//實例化用戶登錄業務層}public void login() {mvcView.showLoading();userLoginMobel.login(mvcView.getUserName(), mvcView.getPassword(), new OnLoginListener() {@Overridepublic void loginSuccess(final UserInfoBean user) {//需要在UI線程執行mHandler.post(new Runnable() {@Overridepublic void run() {mvcView.toMainActivity(user);mvcView.hideLoading();}});}@Overridepublic void loginFailed(final String message) {//需要在UI線程執行mHandler.post(new Runnable() {@Overridepublic void run() {mvcView.showFailedError(message);mvcView.hideLoading();}});}});}public void clear() {mvcView.clearPassword();mvcView.clearUserName();} }

3,view 層
首相定義一個view接口 IUserLoginView
接口規定view層去實現的方法

/*** 完整的登陸接口。 View 接口*/ public interface IUserLoginView {//獲得用戶信息String getUserName();String getPassword();//清除用戶信息void clearUserName();void clearPassword();//遮罩層void showLoading();void hideLoading();//登陸成功void toMainActivity(UserInfoBean user);//登陸失敗void showFailedError(String message); }

我們定義一個MVCActivity來繼承 IUserLoginView

/*** 這時候的activity相當于view (只負責顯示數據)* Presenter與View交互是通過接口*/ public class MVCActivity extends AppCompatActivity implements IUserLoginView {private EditText user_name_edit, user_pwd_edit;private Button user_login_btn, user_clear_btn;private ProgressBar user_login_bar;private UserLoginPresenter presenter;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);presenter=new UserLoginPresenter(this);initView();}private void initView() {user_name_edit = (EditText) findViewById(R.id.user_name_edit);user_pwd_edit = (EditText) findViewById(R.id.user_pwd_edit);user_login_btn = (Button) findViewById(R.id.user_login_btn);user_clear_btn = (Button) findViewById(R.id.user_clear_btn);user_login_bar = (ProgressBar) findViewById(R.id.user_login_bar);user_login_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {presenter.login();}});user_clear_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {presenter.clear();}});}@Overridepublic String getUserName() {return user_name_edit.getText().toString();}@Overridepublic String getPassword() {return user_pwd_edit.getText().toString();}@Overridepublic void clearUserName() {user_name_edit.setText("");}@Overridepublic void clearPassword() {user_pwd_edit.setText("");}@Overridepublic void showLoading() {user_login_bar.setVisibility(View.VISIBLE);}@Overridepublic void hideLoading() {user_login_bar.setVisibility(View.INVISIBLE);}@Overridepublic void toMainActivity(UserInfoBean user) {Toast.makeText(this, user.getUserName(), Toast.LENGTH_SHORT).show();}@Overridepublic void showFailedError(String message) {Toast.makeText(this, message, Toast.LENGTH_SHORT).show();}}

還有layout.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="用戶名" /><EditText android:id="@+id/user_name_edit"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="密碼" /><EditText android:id="@+id/user_pwd_edit"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:orientation="horizontal"><Button android:id="@+id/user_login_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="登陸" /><Button android:id="@+id/user_clear_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="清除" /></LinearLayout><ProgressBar android:id="@+id/user_login_bar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:visibility="invisible" /> </LinearLayout>

我們先來看看效果圖。

可以看出,和我們原來用mvc設計的登陸達到了一樣的目的。但是可以看出我們的activity再也沒有像原來一樣多了很多邏輯處理。
而我們的邏輯處理都放在了Presenter層。而activity成了一個真正的view。

這就是mvp架構最基本的應用。可以看出使用mvp去設計app可以很好的將activity當作一個view層分離出來。

那么從上面的結構圖可以看出我們還是有很多可以優化的地方的。

優化

mobel層 接口都繼承IBaseMobel接口
我們可以在IBaseMobel這個元接口中定義一些整個mobel都會做的工作,例如初始化數據

/*** presenter層基類接口*/ public interface IBaseMobel {void initData();//定義一個所有presenter初始化數據的方法 }

同理:view層 接口都繼承 IBaseView 接口

我們可以在IBaseView 這個元接口中定義一些整個mobel都會做的工作,例如初始化數據。

/*** view層基類接口*/ public interface IBaseView {void initView();//view初始化view的一個基本接口 }

presenter層繼承一個基類來收集重復方法或者屬性
定義一個 BasePresenter類

/*** 在基類presenter中將添加和銷毀方法提供*/ public class BasePresenter<T> {protected T mvcView;/*** 每個繼承基類的presenter都要去實現構造方法,并傳入view層*/protected BasePresenter(T mvcView) {this.mvcView = mvcView;}/*** 因為presenter層持有view層,所以,提供一個方法,在view層不使用的時候將對象釋放*/public void onDestroy() {mvcView = null;} }

我們來看看如何讓原來的UserLoginPresenter使用
修改后的UserLoginPresenter類

/*** 用戶登錄的任命者。Presenter (用于接收模型發出的結果,給view層發送命令)*/ public class UserLoginPresenter extends BasePresenter<IUserLoginView> {private IUserLoginMobel userLoginMobel;//mobel的接口private Handler mHandler = new Handler();public UserLoginPresenter(IUserLoginView userLoginView) {super(userLoginView);//this.userLoginView = userLoginView;//未優化前的方法this.userLoginMobel = new UserLoginModel();//實例化用戶登錄業務層}public void login() {mvcView.showLoading();userLoginMobel.login(mvcView.getUserName(), mvcView.getPassword(), new OnLoginListener() {@Overridepublic void loginSuccess(final UserInfoBean user) {//需要在UI線程執行mHandler.post(new Runnable() {@Overridepublic void run() {mvcView.toMainActivity(user);mvcView.hideLoading();}});}@Overridepublic void loginFailed(final String message) {//需要在UI線程執行mHandler.post(new Runnable() {@Overridepublic void run() {mvcView.showFailedError(message);mvcView.hideLoading();}});}});}public void clear() {mvcView.clearPassword();mvcView.clearUserName();}}

這樣我們就把Presenter的初始化工作和關于activity在onDestory的時候手動置空Presenter中view對象(這時候的view對象其實就是activity)的方法給提取到基類中。

因為這兩個方法很多地方會用到,所以我們不必每次都去寫它們。

我們再將view層的activity封裝。view層例如:fragment也是可以封裝的。

我們建立一個抽象類BaseActivity。

/*** mvc模式的view層基類<繼承 presenter 具體>*/ public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity {//必須實例化presenter對象public abstract T initPresenter();public T presenter;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(setMvcView());presenter = initPresenter();initView();}protected abstract int setMvcView();protected abstract void initView();@Overrideprotected void onDestroy() {presenter.onDestroy();super.onDestroy();} }

接下來修改MVCActivity類

/*** 這時候的activity相當于view (只負責顯示數據)* Presenter與View交互是通過接口*/ public class MVCActivity extends BaseActivity<UserLoginPresenter> implements IUserLoginView {private EditText user_name_edit, user_pwd_edit;private Button user_login_btn, user_clear_btn;private ProgressBar user_login_bar;@Overridepublic UserLoginPresenter initPresenter() {return new UserLoginPresenter(this);}@Overrideprotected int setMvcView() {return R.layout.activity_main;}@Overrideprotected void initView() {user_name_edit = (EditText) findViewById(R.id.user_name_edit);user_pwd_edit = (EditText) findViewById(R.id.user_pwd_edit);user_login_btn = (Button) findViewById(R.id.user_login_btn);user_clear_btn = (Button) findViewById(R.id.user_clear_btn);user_login_bar = (ProgressBar) findViewById(R.id.user_login_bar);user_login_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {presenter.login();}});user_clear_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {presenter.clear();}});}@Overridepublic String getUserName() {return user_name_edit.getText().toString();}@Overridepublic String getPassword() {return user_pwd_edit.getText().toString();}@Overridepublic void clearUserName() {user_name_edit.setText("");}@Overridepublic void clearPassword() {user_pwd_edit.setText("");}@Overridepublic void showLoading() {user_login_bar.setVisibility(View.VISIBLE);}@Overridepublic void hideLoading() {user_login_bar.setVisibility(View.INVISIBLE);}@Overridepublic void toMainActivity(UserInfoBean user) {Toast.makeText(this, user.getUserName(), Toast.LENGTH_SHORT).show();}@Overridepublic void showFailedError(String message) {Toast.makeText(this, message, Toast.LENGTH_SHORT).show();}}

我們把activity的onCreate和onDestory交給基類來處理,我們也可以在基類中處理onResume等方法。所有的生命周期由基類來管理。

另外,我們將Presenter對象也交給基類來管理,讓基類來處理Presenter對象中的公有方法。

mvp架構的應用和優化已經寫完了,我們可以根據自己項目的實際情況作進一步的優化。

mvp其實就是一種設計思想。它不光用于對model、presenter和view的處理。這只是一種思想,可以用到很多地方。

更多的mvp模式可以去參照:

Google在Github開源的一個項目:Android Architecture Blueprints

簡書:Android官方MVP架構項目解析

獻上這篇博客的demo:

demo下載

總結

以上是生活随笔為你收集整理的android MVP——mvp架构的应用和优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。