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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android:四大架构的优缺点,你真的了解吗?

發(fā)布時間:2025/3/15 Android 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android:四大架构的优缺点,你真的了解吗? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


前言

前不久剛結(jié)束對 20 模塊項(xiàng)目的第 3 輪重構(gòu),一路見證 MVC、MVP、Clean 的優(yōu)缺點(diǎn)并形成自己的體會。

近期在總結(jié)工作經(jīng)驗(yàn)的同時,開始寫博客。順便開源了我設(shè)計(jì)的 ViaBus 架構(gòu)。

項(xiàng)目地址:
https://github.com/KunMinX/android-viabus-architecture

項(xiàng)目常用架構(gòu)比對

以下,對常見的 MVC、MVP、Clean、AAC 架構(gòu)做個比對。

首先,一張表格展示各架構(gòu)的類冗余情況:

需求是,寫三個頁面,ListFragment、DetailFragment、PreviewFragment,每個頁面至少用到 3個 Note 業(yè)務(wù)、3個 User 業(yè)務(wù)。問:上述架構(gòu)分別需編寫多少類?

架構(gòu)? ? ? ? ? ? ?涉及類? ? ? ? ? ? ? ? ? ? ? ? ? ? ?類總數(shù)




MVC

Fragment:3個,Controller:3個,Model:2個

8個

MVP

Fragment:3個,Presenter:3個,Model:3個,Contract:1個

10個

Clean

Fragment:3個,ViewModel:3個,Usecase:18個,Model:3個

27個

AAC

Fragment:3個,ViewModel:3個,Model:3個

9個

MVC 架構(gòu)的缺陷

  • View、Controller、Model 相互依賴,造成代碼耦合。

  • 難以分工,難以將 View、Controller、Model 分給不同的人寫。

  • 難以維護(hù),沒有中間件接口做緩沖,難以替換底層的實(shí)現(xiàn)。

public?class?NoteListFragment?extends?BaseFragment?{

...

public?void?refreshList()?{
new?Thread(new?Runnable() {
@Override
public?void?run()?{

//view 中直接依賴 model。那么 view 須等 model 編寫好才能開工。

mNoteList = mDataManager.getNoteList();
mHandler.sendMessage(REFRESH_LIST, mNoteList);
}
}).start();
}

private?Handler mHandler =?new?Handler() {
@Override
public?void?handleMessage(Message msg)?{
switch?(msg) {
case?REFRESH_LIST:
mAdapter.setList(mNoteList);
mAdapter.notifyDataSetChanged();
break;
default:
}
}
};

...
}

MVP 架構(gòu)的特點(diǎn)與局限

  • MVP 架構(gòu)的特點(diǎn)是 面向接口編程。在 View、Presenter、Model 之間分別用 中間件接口 做銜接,當(dāng)有新的底層實(shí)現(xiàn)時,能夠無縫替換。

  • 此外,MVP 的 View 和 Model 并不產(chǎn)生依賴,因此可以說是對 View 和 Model 做了代碼解耦。

public?class?NoteListContract?{

interface?INoteListView?{

void?showDialog(String msg);

void?showTip(String tip);

void?refreshList(List<NoteBean> beans);
}

interface?INoteListPresenter?{

void?requestNotes(String type);

void?updateNotes(NoteBean... beans);

void?deleteNotes(NoteBean... beans);
}

interface?INoteListModel?{

List<NoteBean>?getNoteList();

int?updateNote(NoteBean bean);

int?deleteNote(NoteBean bean);
}
}

但 MVP 架構(gòu)有其局限性。按我的理解,MVP 設(shè)計(jì)的初衷是,?“讓天下沒有難替換的 View 和 Model”?。該初衷背后所基于的假設(shè)是,“上層邏輯穩(wěn)定,但底層實(shí)現(xiàn)更替頻繁” 。在這個假設(shè)的引導(dǎo)下,使得三者中,?只有 Presenter 具備獨(dú)立意志和決定權(quán),掌管著 UI 邏輯和業(yè)務(wù)邏輯,而 View 和 Model 只是外接的工具

public?class?NoteListPresenter?implements?NoteListContract.INoteListPresenter?{

private?NoteListContract.INoteListModel mDataManager;
private?NoteListContract.INoteListView mView;

@Override
public?void?requestNotes(String type)?{
Observable.create(new?ObservableOnSubscribe<List<NoteBean>>() {
@Override
public?void?subscribe(ObservableEmitter<List<NoteBean>> e)?throws?Exception?{
List<NoteBean> noteBeans = mDataManager.getNoteList();
e.onNext(noteBeans);
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new?Consumer<List<NoteBean>>() {
@Override
public?void?accept(List<NoteBean> beans)?throws?Exception?{

//presenter 直接干預(yù)了 UI 在拿到數(shù)據(jù)后做什么,使得邏輯上沒有發(fā)生解耦。

//正常來說,解耦意味著,presenter 的職能邊界僅限返回結(jié)果數(shù)據(jù),
//由 UI 來依據(jù)響應(yīng)碼處理 UI 邏輯。

mView.refreshList(beans);
}
});
}

...
}

然而,這樣的假設(shè)多數(shù)時候并不實(shí)際。可視化需求是變化多端的,在牽涉到視覺交互時,必然涉及 UI 邏輯的修改,也就是說,View 和 Presenter 的相互牽連,使得 UI 的改動需要 View 和 Presenter 編寫者配合著完成,增加溝通協(xié)作成本。

長久來看,二者都難以成長。Presenter 編寫者容易被各種非本職工作拖累,View 的編寫者不會嘗試獨(dú)立自主,例如通過多態(tài)等模式將 UI 封裝成可適應(yīng)性的組件,反正 … 有 Presenter 來各種 if else 嘛。

Clean 架構(gòu)的特點(diǎn)和不足


為解決 Presenter?職能邊界不明確?的問題,在 Clean 架構(gòu)中,業(yè)務(wù)邏輯的職能被轉(zhuǎn)移到領(lǐng)域?qū)?#xff0c;由 Usecase 專職管理。Presenter 則弱化為 ViewModel ,作為代理數(shù)據(jù)請求,和銜接數(shù)據(jù)回調(diào)的緩沖區(qū)。

Clean 架構(gòu)的特點(diǎn)是?單向依賴、數(shù)據(jù)驅(qū)動編程。?View -> ViewModel -> Usecase -> Model?。

View 對 ViewModel 的單向依賴,是通過 databinding 特性實(shí)現(xiàn)的。ViewModel 只負(fù)責(zé)代理數(shù)據(jù)請求,在 Usecase 處理完業(yè)務(wù)返回結(jié)果數(shù)據(jù)時,結(jié)果數(shù)據(jù)被賦值給可觀察的 databinding 數(shù)據(jù),而 View 則依據(jù)數(shù)據(jù)的變化而變化。

public?class?NoteListViewModel?{

private?ObservableList<NoteBean> mListObservable =?new?ObservableArrayList<>();

private?void?requestNotes(String type)?{
if?(null?== mRequestNotesUsecase) {
mRequestNotesUsecase =?new?ProveListInitUseCase();
}

mUseCaseHandler.execute(mRequestNotesUsecase,?new?RequestNotesUsecase.RequestValues(type),
new?UseCase.UseCaseCallback<RequestNotesUsecase.ResponseValue>() {
@Override
public?void?onSuccess(RequestNotesUsecase.ResponseValue response)?{

//viewModel 的可觀察數(shù)據(jù)發(fā)生變化后,databinding 會自動更新 UI 展示。

mListObservable.clear();
mListObservable.addAll(response.getNotes());
}

@Override
public?void?onError()?{

}
});
}

...
}

但 Clean 架構(gòu)也有不足:粒度太細(xì) 。一個 Usecase 受限于請求參數(shù),因而只能處理一類請求。View 請求的數(shù)據(jù)包含幾種類型,就至少需要準(zhǔn)備幾個 Usecase。Usecase 是依據(jù)當(dāng)前 View 對數(shù)據(jù)的需求量身定制的,因此?Usecase 的復(fù)用率極低,項(xiàng)目會因而急劇的增加類和重復(fù)代碼


public?class?RequestNotesUseCase?extends?UseCase<RequestNotesUseCase.RequestValues,?RequestNotesUseCase.ResponseValue>?{

private?DataManager mDataManager;

@Override
protected?void?executeUseCase(final?RequestValues values)?{
List<NoteBean> noteBeans = mDataManager.getNotes();
...
getUseCaseCallback().onSuccess(new?RequestNotesUseCase.ResponseValue(noteBeans));
}

//每新建一個 usecase 類,都需要手動為其配置 請求參數(shù)列表 和 響應(yīng)參數(shù)列表。

public?static?final?class?RequestValues?implements?UseCase.RequestValues?{
private?String type;

public?String?getType()?{
return?type;
}

public?void?setType(String type)?{
this.type = type;
}
}

public?static?final?class?ResponseValue?implements?UseCase.ResponseValue?{

public?List<NoteBean> mBeans;

public?ResponseValue(List<NoteBean> beans)?{
mBeans = beans;
}
}
}

AAC 架構(gòu)的特點(diǎn)

AAC 也是數(shù)據(jù)驅(qū)動編程。只不過它不依賴于 MVVM 特性,而是直接在 View 中寫個觀察者回調(diào),以接收結(jié)果數(shù)據(jù)并處理 UI 邏輯。

public?class?NoteListFragment?extends?BaseFragment?{

@Override
public void onActivityCreated(@Nullable?Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
viewModel.getNote().observe(this, new Observer<NoteBean>() {
@Override
public void onChanged(@Nullable?NoteBean bean) {
//update UI
}
});
}

...
}

你完全可以將其理解為 B/S 架構(gòu):從 Web 前端向 Web 后端發(fā)送了數(shù)據(jù)請求,后端在處理完畢后響應(yīng)結(jié)果數(shù)據(jù)給前端,前端再依據(jù)需求處理 UI 邏輯。等于說,?AAC 將業(yè)務(wù)完全壓到了 Model 層

ViaBus 架構(gòu)的由來及特點(diǎn)

上一輪重構(gòu)項(xiàng)目在用 Clean 架構(gòu),為此我決定跳過 AAC,基于對移動端數(shù)據(jù)交互的理解,編寫“消息驅(qū)動編程”架構(gòu)。

由于借助總線來代理數(shù)據(jù)的請求和響應(yīng),因此取名 ViaBus。


不同于以往的架構(gòu),ViaBus 明確界定了什么是 UI,什么是業(yè)務(wù)。

UI 的作用是視覺交互,為此?UI 的職責(zé)范圍是請求數(shù)據(jù)和處理 UI 邏輯?。業(yè)務(wù)的作用是供應(yīng)數(shù)據(jù),因此?業(yè)務(wù)的職責(zé)范圍是接收請求、處理數(shù)據(jù)、返回結(jié)果數(shù)據(jù)?。

UI 不需要知道數(shù)據(jù)是怎么來的、通過誰來的,它只需向 bus 發(fā)送一個請求,如果有業(yè)務(wù)注冊了該類 “請求處理者”,那么自然有人來處理。業(yè)務(wù)也無需知道 UI 在拿到數(shù)據(jù)后會怎么用,它只需向 bus 回傳結(jié)果,如果有 UI 注冊了“觀察響應(yīng)者”,那么自然有人接收,并依據(jù)響應(yīng)碼行事。

這樣,在靜態(tài) bus 的加持下,UI 和業(yè)務(wù)是完全解耦的,從根本上解決了相互牽連的問題。此外,不同于上述架構(gòu)的每個 View 都要對應(yīng)一個 Presenter 或 ViewModel,在 ViaBus 中,一個模塊中的 UI 可以共享多個“業(yè)務(wù)處理者”實(shí)例,使?代碼的復(fù)用率提升到100%


原文發(fā)布時間為:2018-10-31

本文作者:KunMinX

本文來自云棲社區(qū)合作伙伴“終端研發(fā)部”,了解相關(guān)信息可以關(guān)注“終端研發(fā)部”。

總結(jié)

以上是生活随笔為你收集整理的Android:四大架构的优缺点,你真的了解吗?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。