應用模板代碼地址:https://github.com/thfhongfeng/AndroidAppTemplate
其實所謂架構(gòu)模式言秸,無非是一個通過接口化實現(xiàn)代碼解耦分層的過程吟秩。而接口的實質(zhì)就是一個輸入輸出的規(guī)范仆百。這個規(guī)范成為各個分層代碼的溝通橋梁,使得各個分層只關心自己要做的事堵腹,即告訴我你需要我提供什么(輸出)炸站,并且給我相關的證明(輸入),至于你要用來做什么疚顷,我不關心旱易。
MVP模式
先上通用圖
View發(fā)送指令給Presenter,Presenter獲取指令后腿堤,調(diào)用響應的Model進行業(yè)務邏輯處理阀坏,然后返回數(shù)據(jù)給Presenter,Presenter根據(jù)Model返回的數(shù)據(jù)再來調(diào)用相應的View笆檀。
View:我的服務對象是用戶忌堂,用戶告訴我要給它提供哪些顯示和響應服務,我給出相應的服務误债;
Presenter:我的服務對象是View浸船,View告訴我哪些UI界面需要顯示和響應妄迁,我根據(jù)它提供的內(nèi)容適時的給它提供這些View所需的數(shù)據(jù)內(nèi)容寝蹈;
Model:我的服務對象是Presenter,Presenter告訴我需要哪些業(yè)務數(shù)據(jù)登淘,我根據(jù)它提供的內(nèi)容適時給它提供業(yè)務數(shù)據(jù)箫老。
上圖是mvp架構(gòu)的各個基類,業(yè)務模塊通過繼承這些基類來實現(xiàn)mvp架構(gòu)黔州。
IContract接口集:規(guī)范了Ui(View層)接口和Presenter(Presenter層)接口耍鬓,這里沒有做model層的接口化,實際上這里的接口定義并不是說一定每層都必須要流妻,而應該是根據(jù)自己的項目來靈活處理牲蜀。所謂的架構(gòu)其實只是給了一個分層的規(guī)范,好比一個公司的員工組織架構(gòu):管理做規(guī)劃绅这,技術人員實現(xiàn)產(chǎn)品涣达,客戶經(jīng)理推廣產(chǎn)品,而助理就負責這些崗位的溝通工作。但有時候公司規(guī)模小或者公司性質(zhì)原因度苔,可能就不需要助理而是采用直接溝通的方式匆篓。所以這里接口化的處理是根據(jù)自己項目的性質(zhì)來決定的,選擇適合自己項目的接口化程度能減少項目的開發(fā)成本寇窑。
public interface IContract {
interface Ui {
Activity getContextActivity();
void setLoadingUiVisibility(boolean visibility);
}
interface Presenter {
}
}
IContract只是定義了基本的通用的一些接口鸦概,具體到業(yè)務模塊,通過繼承添加自己的業(yè)務接口甩骏。
IModelAsyncResponse數(shù)據(jù)響應接口:用于Presenter層響應Model層處理結(jié)果窗市。即告訴Model層,我需要T對象横漏。
public interface IModelAsyncResponse<T> {
void onResponse(T t);
boolean onFail(Exception e);
void onCancel();
}
Presenter基類:規(guī)范與UI(View層)的綁定與解綁谨设,定義了一些通用的方法。業(yè)務模塊中通過繼承該類實現(xiàn)Presenter層缎浇。
public abstract class Presenter<V extends IContract.Ui> {
protected final String TAG = LogUtils.makeLogTag(this.getClass());
private UiState mUiState = UiState.UI_STATE_UNDEFINE;
protected boolean mIsLoadProcessing;
/**
* UI的弱引用
*/
private WeakReference<V> mUiRef;
/**
* 關聯(lián)UI
*
* @param ui
*/
@CallSuper
public void attachUi(V ui) {
mUiRef = new WeakReference<V>(ui);
}
/**
* 解除關聯(lián)
*/
@CallSuper
public void detachUi() {
if (mUiRef != null) {
onUiState(UiState.UI_STATE_ON_DETACH);
mUiRef.clear();
}
}
/**
* 得到UI
*
* @return
*/
public V getUi() {
return mUiRef.get();
}
/**
* 得到Application
*
* @return
*/
public Application getApplication() {
return AppUtils.getApplication();
}
/**
* 得到Activity
*
* @return
*/
public Activity getActivity() {
return getUi().getContextActivity();
}
/**
* 得到Context
*
* @return
*/
public Context getContext() {
return getUi().getContextActivity();
}
/**
* 得到Intent
*
* @return
*/
public Intent getIntent() {
if (mUiRef.get() != null) {
if (mUiRef.get() instanceof Activity) {
return ((Activity) mUiRef.get()).getIntent();
} else if (mUiRef.get() instanceof Fragment) {
return ((Fragment) mUiRef.get()).getActivity().getIntent();
} else if (mUiRef.get() instanceof android.support.v4.app.Fragment) {
return ((android.support.v4.app.Fragment) mUiRef.get()).getActivity().getIntent();
}
}
return new Intent();
}
public final boolean isUiAlive() {
if (mUiRef.get() == null) {
return false;
}
if (mUiRef.get() instanceof Activity) {
return !((Activity) mUiRef.get()).isFinishing();
}
return true;
}
public final void finishUi() {
if (mUiRef.get() != null)
if (mUiRef.get() instanceof Activity) {
((Activity) mUiRef.get()).finish();
} else if (mUiRef.get() instanceof Fragment) {
((Fragment) mUiRef.get()).getActivity().finish();
} else if (mUiRef.get() instanceof android.support.v4.app.Fragment) {
((android.support.v4.app.Fragment) mUiRef.get()).getActivity().finish();
}
}
public void setUiLoading(boolean uiLoading) {
mIsLoadProcessing = uiLoading;
if (!isUiAlive()) {
return;
}
getUi().setLoadingUiVisibility(uiLoading);
}
/**
* 用于分析傳入?yún)?shù)是否非法
*
* @return true表示非法扎拣, false表示合法
*/
public boolean parseIntentData(@NonNull Bundle bundle) {
return false;
}
/**
* 用于分析傳入?yún)?shù)是否非法,在View init之后調(diào)用
*
* @return
*/
public void afterViewInit() {
}
/**
* UI狀態(tài)回調(diào)
*
* @param state UI_STATE_ON_CREATE,UI_STATE_ON_START,UI_STATE_ON_RESUME,UI_STATE_ON_PAUSE,
* UI_STATE_ON_STOP,UI_STATE_ON_DETACH
*/
@CallSuper
public void onUiState(UiState state) {
mUiState = state;
}
public UiState getUiState() {
return mUiState;
}
public void showShortToast(String message) {
if (isUiAlive()) {
Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
}
}
public void showShortToast(@StringRes int resId) {
if (isUiAlive()) {
Toast.makeText(getContext(), resId, Toast.LENGTH_SHORT).show();
}
}
public void showLongToast(String message) {
if (isUiAlive()) {
Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
}
}
public void showLongToast(@StringRes int resId) {
if (isUiAlive()) {
Toast.makeText(getContext(), resId, Toast.LENGTH_LONG).show();
}
}
public enum UiState {
UI_STATE_UNDEFINE,
UI_STATE_ON_CREATE,
UI_STATE_ON_START,
UI_STATE_ON_RESUME,
UI_STATE_ON_PAUSE,
UI_STATE_ON_STOP,
UI_STATE_ON_DETACH
}
}
MvpActivity基類:規(guī)范與Presenter(Presenter層)的綁定與解綁素跺,定義了一些通用的方法二蓝。業(yè)務模塊中通過繼承該類實現(xiàn)View層。
注意:該類繼承自筆者自定義的Activity類指厌,而非原生Activity類刊愚。自定義的Activity類實現(xiàn)的內(nèi)容是與架構(gòu)無關的,所以無需擔心踩验。如果直接繼承原生Activity類鸥诽,只需將beforeInitOnCreate, parseIntentData箕憾,afterInit三個方法的內(nèi)容直接按順序移到原生的Activity的onCreate方法中即可牡借。
public abstract class MvpActivity<V extends IContract.Ui, P extends Presenter<V>>
extends Activity implements IContract.Ui {
protected P mPresenter;
@CallSuper
@Override
protected void beforeInitOnCreate(@Nullable Bundle savedInstanceState) {
// 創(chuàng)建并綁定presenter
mPresenter = createPresenter();
if (mPresenter == null) {
Class presenterClazz;
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
presenterClazz = (Class) ((ParameterizedType) type).getActualTypeArguments()[1];
try {
mPresenter = (P) presenterClazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
if (mPresenter != null) {
mPresenter.attachUi((V) this);
} else {
throw new RuntimeException("must initialize a presenter!");
}
}
protected P createPresenter() {
return null;
}
@Override
protected final boolean parseIntentData() {
if (mPresenter != null) {
return mPresenter.parseIntentData(getIntent().getExtras() == null ?
new Bundle() : getIntent().getExtras());
}
return false;
}
@CallSuper
@Override
protected void afterInit() {
if (mPresenter != null) {
mPresenter.onUiState(Presenter.UiState.UI_STATE_ON_CREATE);
mPresenter.afterViewInit();
}
}
@Override
protected void onStart() {
super.onStart();
if (mPresenter != null) {
mPresenter.onUiState(Presenter.UiState.UI_STATE_ON_START);
}
}
@Override
protected void onResume() {
super.onResume();
if (mPresenter != null) {
mPresenter.onUiState(Presenter.UiState.UI_STATE_ON_RESUME);
}
}
@Override
protected void onPause() {
super.onPause();
if (mPresenter != null) {
mPresenter.onUiState(Presenter.UiState.UI_STATE_ON_PAUSE);
}
}
@Override
protected void onStop() {
if (mPresenter != null) {
mPresenter.onUiState(Presenter.UiState.UI_STATE_ON_STOP);
}
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
//解除綁定
if (mPresenter != null) {
mPresenter.detachUi();
}
}
@Override
public android.app.Activity getContextActivity() {
return this;
}
}
MVVM模式
先上通用圖
MVVM是Model-View-ViewModel的簡寫,即模型-視圖-視圖模型袭异∧屏【模型】指的是后端傳遞的數(shù)據(jù),【視圖】指的是所看到的頁面御铃,【視圖模型】mvvm模式的核心碴里,它是連接view和model的橋梁。
MVVM模式相對于MVP模式上真,其實就是將接口化溝通變成了實體化(模型化)溝通咬腋。
簡單來說就是視圖和業(yè)務邏輯的溝通方式不再是命令響應(接口化)的方式,而是具體化的實體模型睡互。即VM提供給View的不再是響應型的數(shù)據(jù)根竿,而是顯示整個View的實體模型溜徙。View響應的是實體模型的改變,而不再是接口的回調(diào)犀填。這樣不僅簡化原先MVP模式下Presenter層與View層的溝通成本蠢壹,還將View的顯示更加組件化,VM與View的綁定可以形成更微小的顯示窗口九巡,以顯示窗口的聚合重用來復用代碼图贸。
其實從命名就可以看出了,VM即View-model冕广,也就是View的model疏日。
實現(xiàn)MVVM的兩個重要的技術:
- DataBinding:完成視圖實體模型與View綁定的利器。
- LiveData:完成視圖實體模型的狀態(tài)化撒汉,讓業(yè)務響應與視圖實體模型的狀態(tài)關聯(lián)起來沟优。
IModelAsyncResponse數(shù)據(jù)響應接口:用于VM層響應Model層處理結(jié)果。即告訴Model層睬辐,我需要T對象挠阁。
這部分與MVP類似
ViewModel視圖模型:定義了一些基本的顯示模型實體。業(yè)務模塊中通過繼承該類實現(xiàn)VM層溯饵。
public abstract class ViewModel extends android.arch.lifecycle.ViewModel {
protected final String TAG = LogUtils.makeLogTag(this.getClass());
private UiState mUiState = UiState.UI_STATE_UNDEFINE;
/**
* UI狀態(tài)回調(diào)
*
* @param state UI_STATE_ON_INIT,UI_STATE_ON_RESUME,UI_STATE_ON_PAUSE,
* UI_STATE_ON_STOP,UI_STATE_ON_DETACH
*/
@CallSuper
public void onUiState(UiState state) {
mUiState = state;
}
public UiState getUiState() {
return mUiState;
}
/**
* 用于分析傳入?yún)?shù)是否非法侵俗,在View init之前調(diào)用
*
* @return true表示非法冻河, false表示合法
*/
public boolean parseIntentData(@NonNull Bundle bundle) {
return false;
}
/**
* 在View init之后調(diào)用
*
* @return
*/
public void afterViewInit() {
}
public void onCleared() {
}
MutableLiveData<Integer> observeSyncLiveData = new MutableLiveData<>();
public MutableLiveData<Integer> getObserveSyncLiveDataData() {
return observeSyncLiveData;
}
/**
* 用于LiveData是其它功能操作返回(不是在VM中初始化賦值)的情況谁帕,
* 在LiveData返回時通過調(diào)用setSyncLiveDataTag來告訴UI開始綁定Observer,
* UI中的必須實現(xiàn)observeSyncLiveData破婆,同時所有其它功能操作返回的LiveData只能在此方法中進行綁定Observer
*
* @param liveDataObjTag 用來標識對應的LiveData(由調(diào)用者自己確定)
*/
public void setSyncLiveDataTag(int liveDataObjTag) {
observeSyncLiveData.setValue(liveDataObjTag);
}
// 重置UI
MutableLiveData<Boolean> resetUiData = new MutableLiveData<>();
public MutableLiveData<Boolean> getResetUiData() {
return resetUiData;
}
public void resetUi() {
resetUiData.setValue(true);
}
// 結(jié)束UI
MutableLiveData<Boolean> finishData = new MutableLiveData<>();
public MutableLiveData<Boolean> getFinishData() {
return finishData;
}
public void finishUi() {
finishData.setValue(true);
}
// 加載中ui顯示狀態(tài)
MutableLiveData<Boolean> uiLoadingData = new MutableLiveData<>();
public MutableLiveData<Boolean> getUiLoadingData() {
return uiLoadingData;
}
public boolean isUiLoading() {
return uiLoadingData.getValue();
}
public void setUiLoading(boolean isLoading) {
uiLoadingData.setValue(isLoading);
}
// Toast ui顯示
MutableLiveData<String> toastMsgData = new MutableLiveData<>();
public MutableLiveData<String> getToastMsgData() {
return toastMsgData;
}
public void setToastMsg(String msg) {
toastMsgData.setValue(msg);
}
MutableLiveData<Integer> toastResIdData = new MutableLiveData<>();
public MutableLiveData<Integer> getToastResIdData() {
return toastResIdData;
}
public void setToastResId(@StringRes Integer id) {
toastResIdData.setValue(id);
}
}
MvvmActivity基類:規(guī)范與VM的綁定與解綁啄巧,定義了一些通用的方法寻歧。業(yè)務模塊中通過繼承該類實現(xiàn)View層。
注意:該類繼承自筆者自定義的Activity類秩仆,而非原生Activity類码泛。自定義的Activity類實現(xiàn)的內(nèi)容是與架構(gòu)無關的,所以無需擔心逗概。如果直接繼承原生Activity類弟晚,只需將beforeInitOnCreate忘衍,setContentView逾苫, findViewOnCreate,parseIntentData枚钓,afterInit五個方法的內(nèi)容直接按順序移到原生的Activity的onCreate方法中即可铅搓。
public abstract class MvvmActivity<T extends ViewDataBinding, VM extends ViewModel> extends Activity {
protected T mBinding;
protected VM mViewModel;
private Observer<Integer> mSyncLiveDataObserver = new Observer<Integer>() {
@Override
public void onChanged(@Nullable Integer tag) {
observeSyncLiveData(tag);
}
};
private Observer<Boolean> mResetUiDataObserver = new Observer<Boolean>() {
@Override
public void onChanged(@Nullable Boolean aBoolean) {
if (aBoolean) {
finish();
startActivity(getIntent());
}
}
};
private Observer<Boolean> mFinishDataObserver = new Observer<Boolean>() {
@Override
public void onChanged(@Nullable Boolean aBoolean) {
if (aBoolean) {
finish();
}
}
};
private Observer<Boolean> mUiLoadingDataObserver = new Observer<Boolean>() {
@Override
public void onChanged(@Nullable Boolean aBoolean) {
setLoadingUiVisibility(aBoolean);
}
};
private Observer<String> mToastMsgDataObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable String msg) {
showShortToast(msg);
}
};
private Observer<Integer> mToastResIdDataObserver = new Observer<Integer>() {
@Override
public void onChanged(@Nullable Integer resId) {
showShortToast(resId);
}
};
@CallSuper
@Override
protected void beforeInitOnCreate(@Nullable Bundle savedInstanceState) {
// 創(chuàng)建ViewModel{
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
Class presenterClazz = (Class) ((ParameterizedType) type).getActualTypeArguments()[1];
mViewModel = (VM) ViewModelProviders.of(this).get(presenterClazz);
mViewModel.getUiLoadingData().setValue(false);
}
mViewModel.getObserveSyncLiveDataData().observe(this, mSyncLiveDataObserver);
mViewModel.getResetUiData().observe(this, mResetUiDataObserver);
mViewModel.getFinishData().observe(this, mFinishDataObserver);
mViewModel.getUiLoadingData().observe(this, mUiLoadingDataObserver);
mViewModel.getToastMsgData().observe(this, mToastMsgDataObserver);
mViewModel.getToastResIdData().observe(this, mToastResIdDataObserver);
observeInitLiveData();
}
/**
* 用于在VM中初始化賦值的LiveData的進行監(jiān)聽觀察
* 此方法在Activity onCreate的時候自動調(diào)用
* (注意區(qū)別于observeSyncLiveData)
* observeInitLiveData:用于在VM中初始化的LiveData的進行監(jiān)聽觀察。
* observeSyncLiveData :用于對不是在VM中初始化賦值的LiveData的進行監(jiān)聽觀察搀捷,需要在VM中主動調(diào)用setSyncLiveDataTag星掰。
*/
public abstract void observeInitLiveData();
protected void setContentView(Bundle savedInstanceState) {
mBinding = DataBindingUtil.setContentView(this, getActivityLayoutResId());
}
@Override
protected final void findViewOnCreate() {
}
@CallSuper
@Override
protected final boolean parseIntentData() {
if (mViewModel != null) {
return mViewModel.parseIntentData(getIntent().getExtras() == null ?
new Bundle() : getIntent().getExtras());
}
return false;
}
@CallSuper
@Override
protected void afterInit() {
if (mViewModel != null) {
mViewModel.onUiState(UiState.UI_STATE_ON_INIT);
}
if (mViewModel != null) {
mViewModel.afterViewInit();
}
}
@Override
protected void onResume() {
super.onResume();
if (mViewModel != null) {
mViewModel.onUiState(UiState.UI_STATE_ON_RESUME);
}
}
@Override
protected void onPause() {
super.onPause();
if (mViewModel != null) {
mViewModel.onUiState(UiState.UI_STATE_ON_PAUSE);
}
}
@Override
protected void onStop() {
if (mViewModel != null) {
mViewModel.onUiState(UiState.UI_STATE_ON_STOP);
}
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
//解除綁定
if (mViewModel != null) {
mViewModel.onUiState(UiState.UI_STATE_ON_DETACH);
}
}
public void setLoadingUiVisibility(boolean visibility) {
}
/**
* 對不是在VM中初始化賦值的LiveData的進行監(jiān)聽觀察(通過其它功能返回的LiveData)多望。
* 此方法的調(diào)用需要在VM獲取到LiveData后中主動調(diào)用setSyncLiveDataTag方法。
* (注意區(qū)別于observeInitLiveData)
* observeInitLiveData:用于在VM中初始化的LiveData的進行監(jiān)聽觀察氢烘。
* observeSyncLiveData :用于對不是在VM中初始化賦值的LiveData的進行監(jiān)聽觀察怀偷,需要在VM中主動調(diào)用setSyncLiveDataTag。
*
* @param liveDataObjTag 用來標識對應的LiveData(由調(diào)用者自己標識)
*/
public abstract void observeSyncLiveData(int liveDataObjTag);
}
各種模式只是規(guī)范化編碼方式的一種總結(jié)播玖,千萬不要為了模式而模式椎工,要根據(jù)自己的項目特性和規(guī)模,選擇合適自己的模式蜀踏。一般來說模式的開發(fā)是針對業(yè)務模塊的维蒙,不同的業(yè)務模塊根據(jù)自己的需求可以使用不同的模式來開發(fā)。
比如:
業(yè)務重用較多的模塊果覆,可以使用MVP模式颅痊。
視圖重用較多或者業(yè)務較復雜的模塊,可以使用MVVM模式局待。
簡單的過渡模塊斑响,直接Android的默認開發(fā)模式就可以了。
不過钳榨,一般的模塊開發(fā)恋捆,還是建議使用MVVM模式。