前言
- 在
Android
開發中,當你梳理完需求后,你要做的并不是馬上寫下你的第一行代碼,而是需先設計好整個項目的技術框架 - 今天,我將全面介紹
Android
開發中主流的技術框架MVC
、MVP
與MVVM
模式,并實例講解MVP
模式,希望您們會喜歡。
目錄
1. 為什么要進行技術框架的設計
- 模塊化功能
使得程序模塊化,即:內部的高聚合、模塊之間的低耦合 - 提高開發效率
開發人員只需專注于某一點(視圖顯示、業務邏輯 / 數據處理) - 提高測試效率
方便后續的測試 & 定位問題
切記:不要為了設計而設計,否則反而會提高開發量
2. Android開發主流的技術框架
- 主要有
MVC
、MVP
、MVVM
3種模式 - 下面,我將詳細 & 具體的介紹上述3種模式
2.1 MVC模式
- 角色說明
- 模式說明
- 該模式存在的問題:Activity責任不明、十分臃腫
Activity
由于其生命周期的功能,除了擔任View
層的部分職責(加載應用的布局、接受用戶操作),還要承擔Controller
層的職責(業務邏輯的處理)
隨著界面的增多 & 邏輯復雜度提高,Activity
類的代碼量不斷增加,越加臃腫
2.2 MVP模式
出現的原因
為了解決上述MVC
模式存在的問題,把分離Activity
中的View
層 和Controller
層的職責,從而對Activity代碼量進行優化、瘦身,所以出現了MVP
模式角色說明
- 模式說明
- 優點:(對比MVC模式)
- 耦合度更低:通過
Presenter
實現數據和視圖之間的交互,完全隔離了View層與Mode層,二者互不干涉
避免了
View
、Model
的直接聯系,又通過Presenter
實現兩者之間的溝通
-
Activity
代碼變得更加簡潔:簡化了Activity
的職責,僅負責UI相關操作,其余復雜的邏輯代碼提取到了Presenter
層中進行處理
2.3 MVVM
為了更加分離M、V層,更加釋放Activity的壓力,于是出現了MVVM模式
- 定義
VM
層:ViewModel
,即 View的數據模型和Presenter的合體
基本上與
MVP
模式完全一致,將邏輯處理層Presenter
改名為ViewModel
- 模式說明
- 優點
使得視圖層(View)
& 控制層(Controller)
之間的耦合程度進一步降低,關注點分離更為徹底,同時減輕了Activity
的壓力
本文主要講解MVC和MVP模式,不過多闡述MVVM模式.
3. MVC、MVP模式的區別
4. 三種模式出現的初衷
-
MVC
模式的出現
為解決程序模塊化問題,于是MVC模式出現了:將業務邏輯、數據處理與界面顯示進行分離來組織代碼,即分成M、V、C層; -
MVP
模式的出現
但M、V層還是有相互交叉、隔離度不夠,同時寫到Activity上使得Activity代碼臃腫,于是出現了MVP: 隔離了MVC中的 M 與 V 的直接聯系,將M、V層更加隔離開來,并釋放了Activity的壓力; -
MVVM
模式的出現
為了更加分離M、V層,更加釋放Activity的壓力,于是出現了MVVM: 使得V和M層之間的耦合程度進一步降低,分離更為徹底,同時更加減輕了Activity的壓力。
下面,我將詳細講解一下最常用的MVP
模式的核心思想 & 使用
5. MVP模式詳解
此處主要詳細分析MVP模式的核心思想,并實例說明。
5.1 核心思想
把Activity里的邏輯都抽離到View
和Presenter
接口中去 & 由具體的實現類來完成。具體實現思路如下:
- 把
Activity
中的UI
邏輯抽象成View
接口 & 由具體的實現類來完成 - 把業務邏輯抽象成
Presenter
接口 & 由具體的實現類來完成 -
Model
類還是原來MVC
模式的Model
層
5.2 實現步驟
MVP
模式的UML
圖
通過UML
圖可看出,使用MVP
模式的步驟如下:
5.3 實例講解
本節通過一個 英語詞典app
實例 講解 MVP
模式具體的實現
前言:工程項目的列表架構
MVP
技術架構的項目結構非常清晰:把M
、V
、P
層分別分為三個文件夾:Model
、View
、Presenter
,每個文件下分別是對應的接口和實現的類
其中
Model
層的fanyi
類是作為實現用GSON
解析JSON
信息的一個JavaBean
步驟1:設置View層(IView接口 & 實現類)
/**
* View接口:IfanyiView
* 需定義在實現類中需要用到的方法
*/
public interface IfanyiView {
void init();//初始化
void SetInfo(String str); //輸出翻譯信息
void SetError(); //輸出出錯信息
}
/**
* View實現類:MainActivity類
* 注:由于MainActivity是對應View層的實現類,所以要實現View層的接口
*/
public class MainActivity extends AppCompatActivity implements IfanyiView {
private EditText et;
private TextView tv;
CidianPresenter cidianPresenter; // 聲明了Presenter對應類
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 實例化P對應類的對象和findView
init();
// 接受用戶的輸入
findViewById(R.id.btnfanyi).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//將View層獲得的數據傳入Presenter層 ,注意還要傳遞MainActivity
cidianPresenter.InputToModel(et.getText().toString(), MainActivity.this);
}
});
}
@Override
public void init(){
//實例化P類的對象和findView
cidianPresenter = new CidianPresenter(this);
et = (EditText) findViewById(R.id.editText);
tv = (TextView) findViewById(R.id.tv);
}
@Override
//輸出出錯信息
public void SetError() {
tv.setText("查詢不成功,請檢查網絡");
}
//輸出翻譯信息
@Override
public void SetInfo(String str){
tv.setText(str);
}
}
// 從上述代碼可看出,MainActivity只做了FindView、setListener的工作(包含了cidianPresenter),簡潔清爽!
步驟2:設置Presenter層(創建IPresenter接口&實現類)
/**
* Presenter接口:ICidianPresenter
* 需定義在實現類中需要用到的方法
*/
public interface ICidianPresenter {
void InputToModel(String input,Context context); // 將View層獲得的數據傳入Model層
}
/**
* Presenter層的實現類:CidianPresenter類
* 注:由于CidianPresenter是對應Presenter層的實現類,所以要實現Presenter層的接口
*/
public class CidianPresenter implements onfanyiListener,ICidianPresenter {
// 1. 聲明View層對應接口、Model層對應的類
IfanyiView fyV;
fanyimodel fanyimodel;
// 2. 重構函數,初始化View接口實例、Model實例
public CidianPresenter(IfanyiView fyV){
this.fyV = fyV;
fanyimodel = new fanyimodel();
}
// 3.將View層獲得的數據傳入Model層,注意要傳遞this.當前類
@Override
public void InputToModel(String input, Context context){
fanyimodel.HandleData(input, context, this);
}
// 回調函數,調用UI更新
@Override
public void onSuccess(String str) {
fyV.SetInfo(str); }
// 回調函數,調用UI輸出出錯信息
@Override
public void onError() {
fyV.SetError(); }
}
// 注:
// a. 保留IfanyiView的引用,就可直接在CidianPresenter當前類進行UI操作而不用在Activity操作
// b. 保留了Model層的引用就可以將View層的數據傳遞到Model層
步驟3:Model層(Model層接口 & 實現類)
/**
* Model層接口:Ifanyi
* 需定義在實現類中需要用到的方法
*/
public interface Ifanyi {
void HandleData(String input,Context context,final onfanyiListener listener);
String fanyiToString(fanyi fy);
}
/**
* Model層的實現類:fanyiModel類
* 注:由于fanyiModel是對應Model層的實現類,所以要實現Model層的接口
*/
public class fanyimodel implements Ifanyi {
private fanyi fy = new fanyi();
public void HandleData(String input,Context context,final onfanyiListener listener){
// 使用Volley框架來實現異步從網絡的有道API獲取翻譯數據
RequestQueue mQueue = Volley.newRequestQueue(context);
StringRequest stringRequest = new StringRequest("http://fanyi.youdao.com/openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q="+input, new Response.Listener<String>() {
@Override
public void onResponse(String s) {
// 用Gson方式解析獲得的json字符串
Gson gson = new Gson();
fy = gson.fromJson(s.trim(),fy.getClass());
// 回調監聽器的函數把處理數據后的結果(翻譯結果)返回給Presenter層
listener.onSuccess(fanyiToString(fy));
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
listener.onError();
}
});
mQueue.add(stringRequest);
}
public String fanyiToString(fanyi fy){
// 處理解析后的json數據,轉成UI輸出的字符串
String strexplain = "解釋:";
String strphonetic = "發音:";
String strweb = "網絡釋義:";
if (fy.basic == null){return "你所查找的還沒有準確翻譯";}
for (int i = 0; i<fy.basic.explains.length; i++){
strexplain +=fy.basic.explains[i]+"\n";
if (i != fy.basic.explains.length-1 )
{strexplain +="\t\t\t\t";}
}
strphonetic += fy.basic.phonetic +"\n";
for (int i = 0; i<fy.web.size(); i++){
for(int j = 0; j<fy.web.get(i).value.length;j++)
{
strweb += fy.web.get(i).value[j]+",";
}
strweb += fy.web.get(i).key+"\n";
strweb += "\t\t\t\t\t\t\t";
}
return strexplain+"\n"+strphonetic+"\n"+strweb;
}
}
至此,關于MVP
模式的實例講解,講解完畢。
6. 總結
- 本文主要講解了
Android
開發中主流的技術框架MVC
、MVP
與MVVM
模式 - 下面我將繼續對
Android
中的知識進行深入講解 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記
相關系列文章閱讀
Carson帶你學Android:學習方法
Carson帶你學Android:四大組件
Carson帶你學Android:自定義View
Carson帶你學Android:異步-多線程
Carson帶你學Android:性能優化
Carson帶你學Android:動畫
歡迎關注Carson_Ho的簡書
不定期分享關于安卓開發的干貨,追求短、平、快,但卻不缺深度。