寫在前邊架構
小夥伴們,兩天不見了,很想念大家哦!這兩天一直沒來得及更新,由於最近在研究 Android 的 MVP 架構,我以爲這也是一個重要的 Android 進階的技術點。框架
昨天我還問我身邊的小夥伴,我問他 「你知道咱們學的 Android 有哪些架構嗎?」 他一臉懵逼的告訴我 「你還別說,Android 的架構我還真不知道。」 他也不算是小白了,學了 Android 也有一年了,正是當年和我一塊兒從安卓基礎學到如今的一個小夥伴。而後我經過這幾天的架構學習簡單和他講了一下,他當時恍然大悟。ide
這就說明一個狀況,你不去主動去學習瞭解這些與 Android 相關技術點,總會被慢慢淘汰的。個人這個小夥伴估計是淘汰不了了,哈哈,他身邊有我指點着呢!post
我充分利用這兩天的空餘時間,經過查看文檔和博客的學習,完全的理解了 MVP 架構的結構。而後把手頭的項目用 MVP 架構作了一遍,也算是入坑了。 學習
從公衆號一開始關注個人讀者知道,我不會爲了發文章而寫文章的,若是手頭真沒有值得分享的技術文章,我是不會隨便寫一篇來應付過去的。從我我的的寫做經驗能夠得出,一篇真正有價值,讓別人可以學習到真正有養分的技術的一篇文章從起草到構思,再到總結整理,最後排版直到成功分享到公衆號至少須要兩個多小時甚至還不夠。曾經我也作過實驗,把一篇技術文用一個小時迅速完成,讀者的收穫每每沒有,閱讀量慘淡,讀者的腦子裏對這個技術點只是一個大致的框架。讀者若是真想借助文章的肩膀往上爬,這還對寫文章的做者有很嚴格的要求的。雖然如今作公衆號的人多了,可是,像張哥說的同樣,高質量的文章仍是屈指可數的。一味地堅持天天發文,你是否考慮到文章的質量呢?廢話很少說,直接上 MVP 架構,今天說啥也讓你弄懂。this
正文線程
介紹 MVP 架構以前,如今簡單瞭解一下MVC 架構,M『 Model 模型層』V『 View 視圖層』C『 Control 控制層』。MVC 架構是一個很適合初學者入門的架構,作 Servlet 後臺服務用的比較多,如今公司基本用 ssm 框架作開發了。MVC 這裏很少深刻介紹,想要了解,網上不少文檔供參考學習。在 Android中 MVC 架構其實不經常使用,也不適合用。由於 View 視圖層和 Control 控制層的代碼都在整個 Activity 中實現的,不能清晰的展示出 View 層和 Control 控制層的所要處理的功能的分離。因此咱們 Android 進一步對 MVC 進行改進,就演化成了如今經常使用到的 MVP 架構 M『 Model 模型層』V『 View 視圖層』P『 Presenter 層』Presenter 用英語翻譯過來就是表明者的意思。他在 MVP 架構中起到什麼做用呢?它的做用就是鏈接 View 層和 Model 層的的橋樑。說白了就是,他是一根電話線,保持兩端的通訊。MVP 和 MVC 的另外一個區別就是,Model 層和 View 視圖層不能直接通訊,而是經過這個 Presenter 這根線的鏈接才能通訊。以前的 MVC 呢?就不能把 Control 控制層看作成電話線了,而是看作成處理邏輯的一個類,View 層和 Control 層還有 Model 層兩兩互相能夠通訊,三者之間的數據傳輸能夠很隨意沒有限制。回過頭來再看 MVP 架構,Model 層和 View 層的數據都會傳到 Presenter 層作二者的處理。寫到這裏不懂沒關係,下面會具體說明。翻譯
咱們再來看一組示意圖:調試
MVC 結構示意圖:code
MVP 結構示意圖
是否是對這兩個架構的區分又清晰了一步?
有小夥伴要着急了,兄弟別廢話了,直接上代碼吧,別來說這些概念了。上邊這些概念是讓你腦子裏造成一個大致的框架,對 MVP 架構有一個基本的認識,纔會對下邊要舉的例子有個清晰的認識。
用 MVP 架構寫一個用戶登陸的例子吧!
第一步 : 包的目錄分佈
總目錄 :
分目錄 :
第二步 : Model層
User 類屬於 bean,爲數據類:
1public class User { 2 private String username ; 3 private String password ; 4 public String getUsername() { 5 return username; 6 } 7 public void setUsername(String username) { 8 this.username = username; 9 } 10 public String getPassword() { 11 return password; 12 } 13 public void setPassword(String password) { 14 this.password = password; 15 } 16}
IOnLoginListener 爲「判斷登陸是否成功」的接口:
1public interface IOnLoginListener { 2 //登陸成功 3 void loginSuccess(User user); 4 //登陸失敗 5 void loginFailed(); 6}
IUserImp 爲登陸功能的接口:
1public interface IUserImp { 2 //登陸 3 public void login(String username, String password, IOnLoginListener loginListener); 4}
UserImp 爲 IUserImp 接口的實現類:
1public class UserImp implements IUserImp { 2 @Override 3 public void login(final String username, final String password, final IOnLoginListener loginListener) { 4 //模擬子線程耗時操做 5 new Thread() { 6 @Override 7 public void run() { 8 try { 9 Thread.sleep(2000); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 //模擬登陸成功 14 if ("zhy".equals(username) && "123".equals(password)) { 15 User user = new User(); 16 user.setUsername(username); 17 user.setPassword(password); 18 loginListener.loginSuccess(user); 19 } else { 20 loginListener.loginFailed(); 21 } 22 } 23 }.start(); 24 } 25}
第三步 : View視圖層
View 中的 IUserLoginView 爲實現與 UI 交互的的方法接口:
1public interface IUserLoginView { 2 //View獲取用戶名和密碼 3 String getUserName(); 4 String getPassword(); 5 //清除用戶名和密碼 6 void clearUserName(); 7 void clearPassword(); 8 //耗時提示ProgressBar 9 void showLoading(); 10 void hideLoading(); 11 //提醒 登陸成功失敗 12 void toMainActivity(User user); 13 void showFailedError(); 14}
第四步 : Presenter 層
Persenter 類中的做用來鏈接 View 層和 Model 層的:
1public class UserLoginPresenter { 2 private IUserImp userBiz; 3 private IUserLoginView userLoginView; 4 private Handler mHandler = new Handler(); 5 public UserLoginPresenter(IUserLoginView userLoginView) { 6 this.userLoginView = userLoginView; 7 this.userBiz = new UserImp(); 8 } 9 public void login() { 10 userLoginView.showLoading(); 11 userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new IOnLoginListener() { 12 @Override 13 public void loginSuccess(final User user) { 14 //須要在UI線程執行 15 mHandler.post(new Runnable() { 16 @Override 17 public void run() { 18 userLoginView.toMainActivity(user); 19 userLoginView.hideLoading(); 20 } 21 }); 22 } 23 @Override 24 public void loginFailed() { 25 //須要在UI線程執行 26 mHandler.post(new Runnable() { 27 @Override 28 public void run() { 29 userLoginView.showFailedError(); 30 userLoginView.hideLoading(); 31 } 32 }); 33 } 34 }); 35 } 36 public void clear() { 37 userLoginView.clearUserName(); 38 userLoginView.clearPassword(); 39 } 40}
第五步 : LoginActivity 去實現登陸功能
1public class UserLoginActivity extends Activity implements IUserLoginView{ 2 private EditText mEtUsername,mEtPassword; 3 private Button mBtnClear,mBtnLogin; 4 private ProgressBar mPbLoading; 5 private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this); 6 @Override 7 protected void onCreate(@Nullable Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 initViews(); 11 } 12 private void initViews() 13 { 14 mEtUsername = (EditText) findViewById(R.id.id_et_username); 15 mEtPassword = (EditText) findViewById(R.id.id_et_password); 16 mBtnClear = (Button) findViewById(R.id.id_btn_clear); 17 mBtnLogin = (Button) findViewById(R.id.id_btn_login); 18 mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading); 19 //登陸 20 mBtnLogin.setOnClickListener(new View.OnClickListener() { 21 @Override 22 public void onClick(View v) { 23 mUserLoginPresenter.login(); 24 } 25 }); 26 //取消登陸 27 mBtnClear.setOnClickListener(new View.OnClickListener() { 28 @Override 29 public void onClick(View v) { 30 mUserLoginPresenter.clear(); 31 } 32 }); 33 } 34 @Override 35 public String getUserName() { 36 return mEtUsername.getText().toString(); 37 } 38 @Override 39 public String getPassword() { 40 return mEtPassword.getText().toString(); 41 } 42 @Override 43 public void clearUserName() { 44 mEtUsername.setText(""); 45 } 46 @Override 47 public void clearPassword() { 48 mEtPassword.setText(""); 49 } 50 @Override 51 public void showLoading() { 52 mPbLoading.setVisibility(View.GONE); 53 } 54 @Override 55 public void hideLoading() { 56 mPbLoading.setVisibility(View.VISIBLE); 57 } 58 @Override 59 public void toMainActivity(User user) { 60 Toast.makeText(this, user.getUsername() + 61 " login success , to MainActivity", Toast.LENGTH_SHORT).show(); 62 } 63 @Override 64 public void showFailedError() { 65 Toast.makeText(this, 66 "login failed", Toast.LENGTH_SHORT).show(); 67 } 68}
當初我學習這個架構的時候有點懵逼,各類你接口各類實現類,弄得我暈頭轉向的。我就一直看一直琢磨,相信最後總會看會的,這些努力和付出最終讓我完全明白了這個叫 MVP 的架構。我給你們提供一個好的方法,經過斷點調試,一步步跟着程序運行,這樣就很容易明白的知道整個架構的邏輯和流程。
咱們經過上邊的一系列學習,有的小夥伴就要問了,怎麼一個簡單的登陸系統怎麼代碼量變多了?沒錯,代碼量是變多了,你有沒有感受到項目邏輯架構清晰了不少?並且每一個架構層中的每一個類都要執行的規定好的任務『 View 視圖層主要管與 UI 界面作交互的(如:監聽用戶按鈕事件);Model 模型層主要是管理數據對象的;Presenter 層主要管理 Model 和 View 的數據通訊處理邏輯運算的』。這種架構作小項目是體現不出有優勢的,等之後到了公司開發大型的項目,代碼量成千上萬,MVP 架構的優點就很明瞭的展示出來,並且包括後期的項目維護,這種優點相比把代碼寫到一個 Activity 裏邊要好的多。好比公司的項目要加一個功能,按照往常的作法,先把整個 Activity 裏邊的邏輯理清,當你理清邏輯,估計公司的黃花菜都涼涼了。然而用 MVP 架構呢,你能夠準確的找到實現該功能的接口,隨意的添加該方法到裏邊,找到實現該方法的實現類而後實現該功能就 ok 了。只有你真正的去作了,才能體會到這種架構的好處,只聽我在這說 bb 沒什麼軟用的。
好了,這兩天我就主要了解了 MVP 架構,有什麼不足可在後臺留言我後期會補充。
後記
爲了今天可以給你們更新干貨,這些大部分都是在上午上課的時候總結的。作一篇乾貨文章真的不容易,這篇文章從開始寫到發佈到公衆號你還被不信,我算了算加起來先後用了三個半小時來更新這篇文章。公衆號高質量的文章也愈來愈少,都是爲了利益絕不顧忌的更新低質量的文章。利益互推、瞎轉發幾乎成了一種常態,我但願個人公衆號一直能這樣高質量的輸出乾貨,經過本身理解總結整合分析反思推敲琢磨,努力打造一個獨一無二純淨的公衆號。