Android App的設計架構:MVC,MVP,MVVM與架構經驗談

 

來源: Android App的設計架構:MVC,MVP,MVVM與架構經驗談

和MVC框架模式同樣,Model模型處理數據代碼不變在Android的App開發中,不少人常常會頭疼於App的架構如何設計:html

  • 個人App須要應用這些設計架構嗎?java

  • MVC,MVP等架構講的是什麼?區別是什麼?android

本文就來帶你分析一下這幾個架構的特性,優缺點,以及App架構設計中應該注意的問題。git

1.架構設計的目的

經過設計使程序模塊化,作到模塊內部的高聚合和模塊之間的低耦合。這樣作的好處是使得程序在開發的過程當中,開發人員只須要專一於一點,提升程序開發的效率,而且更容易進行後續的測試以及定位問題。但設計不能違背目的,對於不一樣量級的工程,具體架構的實現方式必然是不一樣的,切忌犯爲了設計而設計,爲了架構而架構的毛病。github

舉個簡單的例子:數據庫

一個Android App若是隻有3個Java文件,那隻須要作點模塊和層次的劃分就能夠,引入框架或者架構反而提升了工做量,下降了生產力;編程

但若是當前開發的App最終代碼量在10W行以上,本地須要進行復雜操做,同時也須要考慮到與其他的Android開發者以及後臺開發人員之間的同步配合,那就須要在架構上進行一些思考!segmentfault

2.MVC設計架構

微信截圖_20151201004323.png

MVC簡介

MVC全名是Model View Controller,如圖,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,在改進和個性化定製界面及用戶交互的同時,不須要從新編寫業務邏輯。設計模式

其中M層處理數據,業務邏輯等;V層處理界面的顯示結果;C層起到橋樑的做用,來控制V層和M層通訊以此來達到分離視圖顯示和業務邏輯層。緩存

Android中的MVC

Android中界面部分也採用了當前比較流行的MVC框架,在Android中:

  • 視圖層(View)

通常採用XML文件進行界面的描述,這些XML能夠理解爲AndroidApp的View。使用的時候能夠很是方便的引入。同時便於後期界面的修改。邏輯中與界面對應的id不變化則代碼不用修改,大大加強了代碼的可維護性。

  • 控制層(Controller)

Android的控制層的重任一般落在了衆多的Activity的肩上。這句話也就暗含了不要在Activity中寫代碼,要經過Activity交割Model業務邏輯層處理,這樣作的另一個緣由是Android中的Actiivity的響應時間是5s,若是耗時的操做放在這裏,程序就很容易被回收掉。

  • 模型層(Model)

咱們針對業務模型,創建的數據結構和相關的類,就能夠理解爲AndroidApp的Model,Model是與View無關,而與業務相關的(感謝@Xander的講解)。對數據庫的操做、對網絡等的操做都應該在Model裏面處理,固然對業務計算等操做也是必須放在的該層的。就是應用程序中二進制的數據。

MVC代碼實例

咱們來看看MVC在Android開發中是怎麼應用的吧!

先上界面圖

20150606093217165.png

 

Controller控制器&View

public class MainActivity extends ActionBarActivity implements OnWeatherListener, View.OnClickListener { private WeatherModel weatherModel; private EditText cityNOInput; private TextView city; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); weatherModel = new WeatherModelImpl(); initView(); } //初始化View private void initView() { cityNOInput = findView(R.id.et_city_no); city = findView(R.id.tv_city); ... findView(R.id.btn_go).setOnClickListener(this); } //顯示結果 public void displayResult(Weather weather) { WeatherInfo weatherInfo = weather.getWeatherinfo(); city.setText(weatherInfo.getCity()); ... } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_go: weatherModel.getWeather(cityNOInput.getText().toString().trim(), this); break; } } @Override public void onSuccess(Weather weather) { displayResult(weather); } @Override public void onError() { Toast.makeText(this, 獲取天氣信息失敗, Toast.LENGTH_SHORT).show(); } private T findView(int id) { return (T) findViewById(id); } } 

從上面代碼能夠看到,Activity持有了WeatherModel模型的對象,當用戶有點擊Button交互的時候,Activity做爲Controller控制層讀取View視圖層EditTextView的數據,而後向Model模型發起數據請求,也就是調用WeatherModel對象的方法 getWeather()方法。當Model模型處理數據結束後,經過接口OnWeatherListener通知View視圖層數據處理完畢,View視圖層該更新界面UI了。而後View視圖層調用displayResult()方法更新UI。至此,整個MVC框架流程就在Activity中體現出來了。

Model模型

來看看WeatherModelImpl代碼實現

public interface WeatherModel { void getWeather(String cityNumber, OnWeatherListener listener); } ................ public class WeatherModelImpl implements WeatherModel { /*這部分代碼範例有問題,網絡訪問不該該在Model中,應該把網絡訪問換成從數據庫讀取*/ @Override public void getWeather(String cityNumber, final OnWeatherListener listener) { /*數據層操做*/ VolleyRequest.newInstance().newGsonRequest(http://www.weather.com.cn/data/sk/ + cityNumber + .html, Weather.class, new Response.Listener<weather>() { @Override public void onResponse(Weather weather) { if (weather != null) { listener.onSuccess(weather); } else { listener.onError(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { listener.onError(); } }); } } 

以上代碼看出,這裏設計了一個WeatherModel模型接口,而後實現了接口WeatherModelImpl類。controller控制器activity調用WeatherModelImpl類中的方法發起網絡請求,而後經過實現OnWeatherListener接口來得到網絡請求的結果通知View視圖層更新UI 。至此,Activity就將View視圖顯示和Model模型數據處理隔離開了。activity擔當contronller完成了model和view之間的協調做用。

至於這裏爲何不直接設計成類裏面的一個getWeather()方法直接請求網絡數據?你考慮下這種狀況:如今代碼中的網絡請求是使用Volley框架來實現的,若是哪天老闆非要你使用Afinal框架實現網絡請求,你怎麼解決問題?難道是修改 getWeather()方法的實現? no no no,這樣修改不只破壞了之前的代碼,並且還不利於維護, 考慮到之後代碼的擴展和維護性,咱們選擇設計接口的方式來解決着一個問題,咱們實現另一個WeatherModelWithAfinalImpl類,繼承自WeatherModel,重寫裏面的方法,這樣不只保留了之前的WeatherModelImpl類請求網絡方式,還增長了WeatherModelWithAfinalImpl類的請求方式。Activity調用代碼無須要任何修改。

3.MVP設計架構

在App開發過程當中,常常出現的問題就是某一部分的代碼量過大,雖然作了模塊劃分和接口隔離,但也很難徹底避免。從實踐中看到,這更多的出如今UI部分,也就是Activity裏。想象一下,一個2000+行以上基本不帶註釋的Activity,個人第一反應就是想吐。Activity內容過多的緣由其實很好解釋,由於Activity自己須要擔負與用戶之間的操做交互,界面的展現,不是單純的Controller或View。並且如今大部分的Activity還對整個App起到相似IOS中的【ViewController】的做用,這又帶入了大量的邏輯代碼,形成Activity的臃腫。爲了解決這個問題,讓咱們引入MVP框架。

MVC的缺點

在Android開發中,Activity並非一個標準的MVC模式中的Controller,它的首要職責是加載應用的佈局和初始化用戶 界面,並接受並處理來自用戶的操做請求,進而做出響應。隨着界面及其邏輯的複雜度不斷提高,Activity類的職責不斷增長,以至變得龐大臃腫。

什麼是MVP?

MVP從更早的MVC框架演變過來,與MVC有必定的類似性:Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示。

Clipboard Image.png

MVP框架由3部分組成:View負責顯示,Presenter負責邏輯處理,Model提供數據。在MVP模式裏一般包含3個要素(加上View interface是4個):

  • View:負責繪製UI元素、與用戶進行交互(在Android中體現爲Activity)

  • Model:負責存儲、檢索、操縱數據(有時也實現一個Model interface用來下降耦合)

  • Presenter:做爲View與Model交互的中間紐帶,處理與用戶交互的負責邏輯。

  • *View interface:須要View實現的接口,View經過View interface與Presenter進行交互,下降耦合,方便進行單元測試

Tips:*View interface的必要性

回想一下你在開發Android應用時是如何對代碼邏輯進行單元測試的?是否每次都要將應用部署到Android模擬器或真機上,而後經過模擬用 戶操做進行測試?然而因爲Android平臺的特性,每次部署都耗費了大量的時間,這直接致使開發效率的下降。而在MVP模式中,處理複雜邏輯的Presenter是經過interface與View(Activity)進行交互的,這說明咱們能夠經過自定義類實現這個interface來模擬Activity的行爲對Presenter進行單元測試,省去了大量的部署及測試的時間。

MVC → MVP

當咱們將Activity複雜的邏輯處理移至另外的一個類(Presenter)中時,Activity其實就是MVP模式中的View,它負責UI元素的初始化,創建UI元素與Presenter的關聯(Listener之類),同時本身也會處理一些簡單的邏輯(複雜的邏輯交由 Presenter處理)。

MVP的Presenter是框架的控制者,承擔了大量的邏輯操做,而MVC的Controller更多時候承擔一種轉發的做用。所以在App中引入MVP的緣由,是爲了將此前在Activty中包含的大量邏輯操做放到控制層中,避免Activity的臃腫。

兩種模式的主要區別:

  • (最主要區別)View與Model並不直接交互,而是經過與Presenter交互來與Model間接交互。而在MVC中View能夠與Model直接交互
  • 一般View與Presenter是一對一的,但複雜的View可能綁定多個Presenter來處理邏輯。而Controller是基於行爲的,而且能夠被多個View共享,Controller能夠負責決定顯示哪一個View
  • Presenter與View的交互是經過接口來進行的,更有利於添加單元測試。

MVC與MVP區別

所以咱們能夠發現MVP的優勢以下:

一、模型與視圖徹底分離,咱們能夠修改視圖而不影響模型;

二、能夠更高效地使用模型,由於全部的交互都發生在一個地方——Presenter內部;

三、咱們能夠將一個Presenter用於多個視圖,而不須要改變Presenter的邏輯。這個特性很是的有用,由於視圖的變化老是比模型的變化頻繁;

四、若是咱們把邏輯放在Presenter中,那麼咱們就能夠脫離用戶接口來測試這些邏輯(單元測試)。

 

具體到Android App中,通常能夠將App根據程序的結構進行縱向劃分,根據MVP能夠將App分別爲模型層(M),UI層(V)和邏輯層(P)。

UI層通常包括Activity,Fragment,Adapter等直接和UI相關的類,UI層的Activity在啓動以後實例化相應的Presenter,App的控制權後移,由UI轉移到Presenter,二者之間的通訊經過BroadCast、Handler或者接口完成,只傳遞事件和結果。

舉個簡單的例子,UI層通知邏輯層(Presenter)用戶點擊了一個Button,邏輯層(Presenter)本身決定應該用什麼行爲進行響應,該找哪一個模型(Model)去作這件事,最後邏輯層(Presenter)將完成的結果更新到UI層。

**MVP的變種:Passive View

MVP的變種有不少,其中使用最普遍的是Passive View模式,即被動視圖。在這種模式下,View和Model之間不能直接交互,View經過Presenter與Model打交道。Presenter接受View的UI請求,完成簡單的UI處理邏輯,並調用Model進行業務處理,並調用View將相應的結果反映出來。View直接依賴Presenter,可是Presenter間接依賴View,它直接依賴的是View實現的接口。

clip_image002[4]_thumb.jpg

相對於View的被動,那Presenter就是主動的一方。對於Presenter的主動,有以下的理解:

  • Presenter是整個MVP體系的控制中心,而不是單純的處理View請求的人;
  • View僅僅是用戶交互請求的彙報者,對於響應用戶交互相關的邏輯和流程,View不參與決策,真正的決策者是Presenter;
  • View向Presenter發送用戶交互請求應該採用這樣的口吻:「我如今將用戶交互請求發送給你,你看着辦,須要個人時候我會協助你」,不該該是這樣:「我如今處理用戶交互請求了,我知道該怎麼辦,可是我須要你的支持,由於實現業務邏輯的Model只信任你」;
  • 對於綁定到View上的數據,不該該是View從Presenter上「拉」回來的,應該是Presenter主動「推」給View的;
  • View儘量不維護數據狀態,由於其自己僅僅實現單純的、獨立的UI操做;Presenter纔是整個體系的協調者,它根據處理用於交互的邏輯給View和Model安排工做。

MVP架構存在的問題與解決辦法

  • 加入模板方法(Template Method)

轉移邏輯操做以後可能部分較爲複雜的Activity內代碼量仍是很多,因而須要在分層的基礎上再加入模板方法(Template Method)。

具體作法是在Activity內部分層。其中最頂層爲BaseActivity,不作具體顯示,而是提供一些基礎樣式,Dialog,ActionBar在內的內容,展示給用戶的Activity繼承BaseActivity,重寫BaseActivity預留的方法。若有必要再進行二次繼承,App中Activity之間的繼承次數最多不超過3次。

  • Model內部分層

模型層(Model)中的總體代碼量是最大的,通常由大量的Package組成,針對這部分須要作的就是在程序設計的過程當中,作好模塊的劃分,進行接口隔離,在內部進行分層。

  • 強化Presenter

強化Presenter的做用,將全部邏輯操做都放在Presenter內也容易形成Presenter內的代碼量過大,對於這點,有一個方法是在UI層和Presenter之間設置中介者Mediator,將例如數據校驗、組裝在內的輕量級邏輯操做放在Mediator中;在Presenter和Model之間使用代理Proxy;經過上述二者分擔一部分Presenter的邏輯操做,但總體框架的控制權仍是在Presenter手中。Mediator和Proxy不是必須的,只在Presenter負擔過大時才建議使用。

最終的架構以下圖所示:

1422253914_8854.jpg

MVP代碼實例

咱們來看看MVP在Android開發中是怎麼應用的吧!!

咱們用另外一個例子來解釋。

先來看包結構圖

20140928093820322.png

 

創建Bean

public class UserBean {      private String mFirstName;      private String mLastName;      public UserBean(String firstName, String lastName) {             this. mFirstName = firstName;             this. mLastName = lastName;      }      public String getFirstName() {             return mFirstName;      }      public String getLastName() {             return mLastName;      } }

 

創建Model

(處理業務邏輯,這裏指數據讀寫),先寫接口,後寫實現

public interface IUserModel { void setID(int id); void setFirstName(String firstName); void setLastName(String lastName); int getID(); UserBean load(int id);// 經過id讀取user信息,返回一個UserBean } 

實現不在這裏寫了

 

Presenter控制器

創建presenter(主導器,經過iView和iModel接口操做model和view),activity能夠把全部邏輯給presenter處理,這樣java邏輯就從手機的activity中分離出來。

public class UserPresenter { private IUserView mUserView; private IUserModel mUserModel; public UserPresenter(IUserView view) { mUserView = view; mUserModel = new UserModel(); } public void saveUser( int id, String firstName, String lastName) { mUserModel.setID(id); mUserModel.setFirstName(firstName); mUserModel.setLastName(lastName); } public void loadUser( int id) { UserBean user = mUserModel.load(id); mUserView.setFirstName(user.getFirstName()); // 經過調用IUserView的方法來更新顯示 mUserView.setLastName(user.getLastName()); } } 

 

View視圖

創建view(更新ui中的view狀態),這裏列出須要操做當前view的方法,也是接口

public interface IUserView { int getID(); String getFristName(); String getLastName(); void setFirstName(String firstName); void setLastName(String lastName); } 

activity中實現iview接口,在其中操做view,實例化一個presenter變量。

public class MainActivity extends Activity implements OnClickListener,IUserView { UserPresenter presenter; EditText id,first,last; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_main); findViewById(R.id. save).setOnClickListener( this); findViewById(R.id. load).setOnClickListener( this); id = (EditText) findViewById(R.id. id); first = (EditText) findViewById(R.id. first); last = (EditText) findViewById(R.id. last); presenter = new UserPresenter( this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id. save: presenter.saveUser(getID(), getFristName(), getLastName()); break; case R.id. load: presenter.loadUser(getID()); break; default: break; } } @Override public int getID() { return new Integer( id.getText().toString()); } @Override public String getFristName() { return first.getText().toString(); } @Override public String getLastName() { return last.getText().toString(); } @Override public void setFirstName(String firstName) { first.setText(firstName); } @Override public void setLastName(String lastName) { last.setText(lastName); } } 

所以,Activity及從MVC中的Controller中解放出來了,這會Activity主要作顯示View的做用和用戶交互。每一個Activity能夠根據本身顯示View的不一樣實現View視圖接口IUserView。

經過對比同一實例的MVC與MVP的代碼,能夠證明MVP模式的一些優勢:

  • 在MVP中,Activity的代碼不臃腫;
  • 在MVP中,Model(IUserModel的實現類)的改動不會影響Activity(View),二者也互不干涉,而在MVC中會;
  • 在MVP中,IUserView這個接口能夠實現方便地對Presenter的測試;
  • 在MVP中,UserPresenter能夠用於多個視圖,可是在MVC中的Activity就不行。

4.MVC、MVP與MVVM的關係

首先介紹下MVVM。

MVVM

MVVM能夠算是MVP的升級版,其中的VM是ViewModel的縮寫,ViewModel能夠理解成是View的數據模型和Presenter的合體,ViewModel和View之間的交互經過Data Binding完成,而Data Binding能夠實現雙向的交互,這就使得視圖和控制層之間的耦合程度進一步下降,關注點分離更爲完全,同時減輕了Activity的壓力。

在比較以前,先從圖上看看三者的異同。

2f9e4ee7d9616257ab41de204c06ffd5_b.jpg

剛開始理解這些概念的時候認爲這幾種模式雖然都是要將view和model解耦,可是非此即彼,沒有關係,一個應用只會用一種模式。後來慢慢發現世界絕對不是隻有黑白兩面,中間最大的一塊實際上是灰色地帶,一樣,這幾種模式的邊界並不是那麼明顯,可能你在本身的應用中都會用到。實際上也根本不必去糾結本身到底用的是MVC、MVP仍是MVVP,無論黑貓白貓,捉住老鼠就是好貓。

MVC->MVP->MVVM演進過程

MVC -> MVP -> MVVM 這幾個軟件設計模式是一步步演化發展的,MVVM 是從 MVP 的進一步發展與規範,MVP 隔離了MVC中的 M 與 V 的直接聯繫後,靠 Presenter 來中轉,因此使用 MVP 時 P 是直接調用 View 的接口來實現對視圖的操做的,這個 View 接口的東西通常來講是 showData、showLoading等等。M 與 V已經隔離了,方便測試了,但代碼還不夠優雅簡潔,因此 MVVM 就彌補了這些缺陷。在 MVVM 中就出現的 Data Binding 這個概念,意思就是 View 接口的 showData 這些實現方法能夠不寫了,經過 Binding 來實現。

若是把這三者放在一塊兒比較,先說一下三者的共同點,也就是Model和View:

  • Model:數據對象,同時,提供本應用外部對應用程序數據的操做的接口,也可能在數據變化時發出變動通知。Model不依賴於View的實現,只要外部程序調用Model的接口就可以實現對數據的增刪改查。

  • View:UI層,提供對最終用戶的交互操做功能,包括UI展示代碼及一些相關的界面邏輯代碼。

三者的差別在於如何粘合View和Model,實現用戶的交互操做以及變動通知

  • Controller

Controller接收View的操做事件,根據事件不一樣,或者調用Model的接口進行數據操做,或者進行View的跳轉,從而也意味着一個Controller能夠對應多個View。Controller對View的實現不太關心,只會被動地接收,Model的數據變動不經過Controller直接通知View,一般View採用觀察者模式監聽Model的變化。

  • Presenter

Presenter與Controller同樣,接收View的命令,對Model進行操做;與Controller不一樣的是Presenter會副作用於View,Model的變動通知首先被Presenter得到,而後Presenter再去更新View。一個Presenter只對應於一個View。根據Presenter和View對邏輯代碼分擔的程度不一樣,這種模式又有兩種狀況:Passive View和Supervisor Controller。

  • ViewModel

注意這裏的「Model」指的是View的Model,跟MVVM中的一個Model不是一回事。所謂View的Model就是包含View的一些數據屬性和操做的這麼一個東東,這種模式的關鍵技術就是數據綁定(data binding),View的變化會直接影響ViewModel,ViewModel的變化或者內容也會直接體如今View上。這種模式其實是框架替應用開發者作了一些工做,開發者只須要較少的代碼就能實現比較複雜的交互。

一點心得

MVP和MVVM徹底隔離了Model和View,可是在有些狀況下,數據從Model到ViewModel或者Presenter的拷貝開銷很大,可能也會結合MVC的方式,Model直接通知View進行變動。在實際的應用中頗有可能你已經在不知不覺中將幾種模式融合在一塊兒,可是爲了代碼的可擴展、可測試性,必須作到模塊的解耦,不相關的代碼不要放在一塊兒。網上有一個故事講,一我的在一家公司作一個新產品時,一名外包公司的新員工直接在View中作了數據庫持久化操做,並且一個hibernate代碼展開後發現居然有幾百行的SQL語句,搞得他們驚訝不已,一時成爲笑談。

我的理解,在廣義地談論MVC架構時,並不是指本文中嚴格定義的MVC,而是指的MV*,也就是視圖和模型的分離,只要一個框架提供了視圖和模型分離的功能,咱們就能夠認爲它是一個MVC框架。在開發深刻以後,能夠再體會用到的框架究竟是MVC、MVP仍是MVVM。

5. 基於AOP的框架設計

AOP(Aspect-Oriented Programming, 面向切面編程),誕生於上個世紀90年代,是對OOP(Object-Oriented Programming, 面向對象編程)的補充和完善。OOP引入封裝、繼承和多態性等概念來創建一種對象層次結構,用以模擬公共行爲的一個集合。當咱們須要爲分散的對象引入公共行爲的時候,OOP則顯得無能爲力。也就是說,OOP容許你定義從上到下的關係,但並不適合定義從左到右的關係。例如日誌功能。日誌代碼每每水平地散佈在全部對象層次中,而與它所散佈到的對象的核心功能毫無關係。對於其餘類型的代碼,如安全性、異常處理和透明的持續性也是如此。這種散佈在各處的無關的代碼被稱爲橫切(Cross-Cutting)代碼,在OOP設計中,它致使了大量代碼的重複,而不利於各個模塊的重用。而AOP技術則偏偏相反,它利用一種稱爲「橫切」的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,並將其名爲「Aspect」,即方面。所謂「方面」,簡單地說,就是將那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,便於減小系統的重複代碼,下降模塊間的耦合度,並有利於將來的可操做性和可維護性。

aop2.1.gif

5.1 AOP在Android中的使用

AOP把軟件系統分爲兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的一個特色是,他們常常發生在覈心關注點的多處,而各處都基本類似。AOP的做用在於分離系統中的各類關注點,將核心關注點和橫切關注點分離開來。在Android App中,哪些是咱們須要的橫切關注點?我的認爲主要包括如下幾個方面:Http, SharedPreferences, Json, Xml, File, Device, System, Log, 格式轉換等。Android App的需求差異很大,不一樣的需求橫切關注點必然是不同的。通常的App工程中應該有一個Util Package來存放相關的切面操做,在項目多了以後能夠將其中使用較多的Util封裝爲一個Jar包供工程調用。

在使用MVP和AOP對App進行縱向和橫向的切割以後,可以使得App總體的結構更清晰合理,避免局部的代碼臃腫,方便開發、測試以及後續的維護。

6. 乾貨:AndroidApp架構的設計經驗

首先是做者最最喜歡的一句話,也是對創業公司特別適用的一句話,也是對不要過分設計的一種詮釋:

先實現,再重構吧。直接考慮代碼不臃腫得話,不知道何時才能寫好了joy

先實現,再重構吧。直接考慮代碼不臃腫得話,不知道何時才能寫好了joy

先實現,再重構吧。直接考慮代碼不臃腫得話,不知道何時才能寫好了joy

(重要的事情說三遍sunglasses

6.1 總體架構

代碼和文檔規範,根據需求進行模塊劃分,肯定交互方式,造成接口文檔,這些較爲通用的內容再也不細說。作Android App時,通常將App進行縱向和橫向的劃分。縱向的App由UI層,邏輯層和模型層構成,總體結構基於MVP思想(圖片來自網絡)。

9fe1e5679a642f9f82373d2a32d461b7_b.jpg

UI層內部多用模板方法,以Activity爲例通常有BaseActivity,提供包括一些基礎樣式,Dialog,ActionBar在內的內容,展示的Activity都會繼承BaseActivity並實現預留的接口,Activity之間的繼承不超過3次;爲避免Activity內代碼過多,將App的總體控制權後移,也借鑑了IOC作法,大量的邏輯操做放在邏輯層中,邏輯層和UI層經過接口或者Broadcast等實現通訊,只傳遞結果。通常Activity裏的代碼量都很大,經過這兩種方式通常我寫的單個Activity內代碼量不超過400行。

邏輯層實現的是絕大部分的邏輯操做,由UI層啓動,在內部經過接口調用模型層的方法,在邏輯層內大量使用了代理。打個比方,UI層告訴邏輯層我須要作的事,邏輯層去找相應的人(模型層)去作,最後只告訴UI這件事作的結果。

模型層沒什麼好說的,這部分通常由大量的Package組成,代碼量是三層中最大的,須要在內部進行分層。

橫向的分割依據AOP面向切面的思想,主要是提取出共用方法做爲一個單獨的Util,這些Util會在App總體中穿插使用。不少人的App都會引入本身封裝的Jar包,封裝了包括文件、JSON、SharedPreference等在內的經常使用操做,本身寫的用起來順手,也大幅度下降了重複做業。

這樣縱,橫兩次對於App代碼的分割已經能使得程序不會過多堆積在一個Java文件裏,但靠一次開發過程就寫出高質量的代碼是很困難的,趁着項目的間歇期,對代碼進行重構頗有必要。

6.2 類庫的使用

如今有不少幫助快速開發的類庫,活用這些類庫也是避免代碼臃腫和混亂的好方法,下面給題主推薦幾個經常使用類庫。

減小Activity代碼量的依賴注入框架ButterKnife:

https://github.com/JakeWharton/butterknife

簡化對於SQlite操做的對象關係映射框架OrmLite:

https://github.com/j256/ormlite-android

圖片緩存類庫Fresco(by facebook):

https://github.com/facebook/fresco

能用第三方庫就用第三方庫。別管是否穩定,是否被持續維護,由於,任何第三方庫的做者,都能碾壓剛入門的菜鳥,你絕對寫不出比別人更好的代碼了。

最後附上知乎上面點贊次數很高的一段話: 

若是「從零開始」,用什麼設計架構的問題屬於想得太多作得太少的問題。

從零開始意味着一個項目的主要技術難點是基本功能實現。當每個功能都須要考慮如何作到的時候,我以爲通常人都沒辦法考慮如何作好。

由於,全部的優化都是站在最上層進行統籌規劃。在這以前,你必須對下層的每個模塊都很是熟悉,進而提煉可複用的代碼、規劃邏輯流程。

因此,若是真的是從零開始,別想太多了wink

 

參考文獻:

一、http://blog.csdn.net/luyi325xyz/article/details/43085409

二、http://blog.csdn.net/napolunyishi/article/details/22722345

三、https://www.zhihu.com/question/27645587/answer/37579829

四、http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0202/2397.html

五、http://www.tuicool.com/articles/VJZrYb

六、https://www.zhihu.com/question/27645587

七、http://blog.csdn.net/luyi325xyz/article/details/43482123

八、https://www.zhihu.com/question/30976423

九、http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0313/2599.html

十、http://www.2cto.com/kf/201506/405766.html

十一、https://www.zhihu.com/question/19766132

十二、http://www.cnblogs.com/artech/archive/2010/03/25/1696205.html

1三、http://www.javashuo.com/article/p-qscgrebs-gb.html

1四、http://blog.csdn.net/knxw0001/article/details/39637273

 

相關:

android MVC && MVP && MVVM分析和對比

Google 官方MVP Demo 

Android MVP 詳解(上)

Android MVP 詳解(下) 

相關文章
相關標籤/搜索