IT觀察】網絡通訊、圖片顯示、數據庫操做……Android程序員如何利用開源框架

每一個Android 程序員都不是Android應用開發之路上孤軍奮戰的一我的,GitHub上浩如煙海的開源框架或類庫就是前人爲咱們發明的輪子,有的輪子能提升軟件性能,而有的輪子彷佛是以犧牲性能爲代價換取編程速度。擅長利用輪子的程序員已經遙遙領先,不擅長利用輪子的程序員老是嫌前人發明的輪子不夠圓,本身造個方輪子上路後才發現落後了。javascript

做者:玖哥來源:51CTO|2017-10-19 16:06

 


【51CTO.com原創稿件】每一個Android 程序員都不是Android應用開發之路上孤軍奮戰的一我的,GitHub上浩如煙海的開源框架或類庫就是前人爲咱們發明的輪子,有的輪子能提升軟件性能,而有的輪子彷佛是以犧牲性能爲代價換取編程速度。擅長利用輪子的程序員已經遙遙領先,不擅長利用輪子的程序員老是嫌前人發明的輪子不夠圓,本身造個方輪子上路後才發現落後了。java

輪子

技術選型的考量點android

來自不一樣行業、面向不一樣用戶的App對功能特性、各方面性能的要求都是不一樣的,選擇開源框架和類庫不能掉以輕心,咱們在選擇開源框架以前務必要選擇幾個考量點進行技術選型。咱們選擇開源框架能夠從如下三個方面考慮(排名有前後):程序員

一、功能特性:提供的特性是否知足項目的需求。好比Picasso不支持GIF圖和視頻縮略圖等,不適合視頻應用。web

二、編程效率:是否有默認參數,配置是否複雜。是否能夠一鍵調用,不須要二次封裝。API是否簡潔易懂,能夠望文生義。僅在module的build.gradle裏依賴和還須要在project的build.gradle裏依賴對程序員細心程度的要求是不同的,而且須要開發者配置參數的UIL被Picasso取代也不足爲奇。算法

三、性能:處理速度不能太慢,穩定性也不能太差,佔用內存不該該過高,jar的體積能夠不能太大。此外過大的jar包必定包含過多的方法數,積累起來會致使你的APP遇到64K問題。Fresco的體積就太大了點。sql

我爲何要把編程效率排在性能以前,由於程序員的工資每一年都在上漲,常常出現薪資倒掛現象,而同等價格的Android設備的性能每18個月翻一番。再舉一個極端的例子:「實現「3的3次方」有三種寫法:數據庫

「3^3」、「3*3*3」、「(3+3+3)+(3+3+3)+(3+3+3)」,顯然正常人都會用第一種方法,但第三種方法的性能纔是最好的。編程

肯定了技術選型的考量點之後,咱們接下來要肯定最經常使用的六大類開源框架的選型:json

1、網絡通訊

Android程序員都是移動互聯網開發者,不多有不依賴網絡的App,網絡權限幾乎是每一個App必然要申請的權限,網絡通訊框架的選擇也是一個App項目中技術選型的最重要組成部分。

android-async-http

android-async-http是Android最經典的網絡異步通訊框架,它對Apache的HttpClient API的封裝使得開發者能夠簡潔優雅地實現網絡請求和響應。由於Android 6.0之後去掉了HttpClient,這就敲響了android-async-http的喪鐘,目前已經不多有人使用這個框架。

OkHttp

OkHttp是Square出品的一個簡潔、快速、高效的HTTP客戶端,支持HTTP/2以及SPDY,扮演着傳輸層的角色。它既能在網絡性能不好的狀況下很好地工做,也可以避免常見的網絡鏈接問題。OkHttp的常規用法:

  1. OkHttpClient okHttpClient = new OkHttpClient(); 
  2. Request request = new Request.Builder() 
  3.         .url("http://短鏈接") 
  4.         .build(); 
  5. Call call = okHttpClient.newCall(request); 
  6. call.enqueue(new Callback() { 
  7.     @Override 
  8.     public void onFailure(Call call, IOException e) { 
  9.         e.printStackTrace(); 
  10.     } 
  11.  
  12.     @Override 
  13.     public void onResponse(Call call 
  14.             , Response response) throws IOException { 
  15.     } 
  16. }); 

 

儘管名字帶有「Http」,但OkHttp的功能並不侷限於http請求。之前的版本能夠經過插件來實現WebSocket長鏈接,而3.5之後的版本則直接支持WebSocket:

  1. OkHttpClient client = new OkHttpClient 
  2.         .Builder() 
  3.         .readTimeout(0,  
  4.                 TimeUnit.MILLISECONDS) 
  5.         .build(); 
  6. Request request = new Request 
  7.         .Builder() 
  8.         .url("ws://ws打頭的連接就是長鏈接") 
  9.         .build(); 
  10.  
  11. WebSocket webSocket = client 
  12.         .newWebSocket(request, new WebSocketListener() { 
  13.     @Override 
  14.     public void onMessage(WebSocket webSocket, String text) { 
  15.         super.onMessage(webSocket, text); 
  16.     } 
  17.  
  18.     @Override 
  19.     public void onFailure(WebSocket webSocket,  
  20.                           Throwable t, Response response) { 
  21.         super.onFailure(webSocket, t, response); 
  22.     } 
  23. }); 

 

Volley

Volley是Google開發的一個簡化網絡任務的庫。Volley側重於Request的隊列的管理,適合請求、加載、緩存、多線程、同步等各種任務,尤爲能使數據量小但通訊頻繁的場景中的網絡通訊更快、更簡單、更健壯。Volley的常規用法:

  1. StringRequest stringRequest = new StringRequest(Request.Method.GET 
  2.         ,"http://普通Volley" 
  3.         , new Response.Listener<String>() { 
  4.             @Override 
  5.             public void onResponse(String response) { 
  6.  
  7.             } 
  8.         }, new Response.ErrorListener() { 
  9.     @Override 
  10.     public void onErrorResponse(VolleyError error) { 
  11.         error.printStackTrace(); 
  12.     } 
  13. }); 
  14.  
  15. Volley.newRequestQueue(this).add(stringRequest); 

 

Volley在頻繁訪問服務器有很大的優點,OkHttp在性能、速度方面優點明顯一,點。咱們能夠用OkHttp來擴展Volley,這樣能讓兩者取長補短。

Retrofit

Retrofit並非一個單純的網絡請求函數框架,而是能直接請求獲得實體類的整套組合框架。Retrofit默認使用Gson做爲JSON解析器,默認使用OkHttp實現網絡請求,同時基於註解使得代碼變得很是簡潔,固然咱們也能夠將OkHttp和Gson換成其餘的函數庫。

【小結】我我的不建議使用有點過分封裝的Retrofit,尤爲當一個App的團隊業務較複雜或人員變更太頻繁而致使域名前綴、header、contentType等變化太多時。數據量小但通訊頻繁的App,例若有輪詢等功能的時候適合用Volley,而中等以上體量的App則適合用OkHttp,但我更建議把OkHttp和Volley結合在一塊兒使用。

2、圖片緩存與顯示

圖片從來是Android手機中的吃內存大戶,稍不留意就會出現OOM,因此可否作好圖片的緩存是一個App性能好壞的決定性指標,對圖片緩存與顯示框架的技術選型不得不重視。

Universal-Image-Loader

Universal-Image-Loader(如下簡稱UIL)是Android平臺老牌的圖片緩存與顯示框架,也是大多數3年以上的Android程序員入行以來接觸的第一個框架。功能強大靈活且高度可自定義,所以在Picasso流行開來以前一直是最流行的Android圖片加載庫,目前仍有大量開發者使用。

Picasso

Picasso是著名的Square公司衆多開源項目中的一個,最顯著的優勢就是體積很是輕小,僅有120KB,也所以經常成爲衆多深刻研讀源碼的程序員第一個研讀的框架。

  1. Picasso.with(this) 
  2.         .load("圖片地址:url或path") 
  3.         .placeholder(R.mipmap.ic_launcher) 
  4.         .error(R.mipmap.ic_launcher) 
  5.         .resize(100,100) 
  6.         .centerCrop() 
  7.         .centerInside() 
  8.         .into(imageView); 

 

Glide

Glide是Google官方推薦的用於Android平臺上的圖片加載和緩存庫,被普遍應用在Google的開源項目中。Glide除了爲包含圖片的滾動列表()作了儘量流暢的優化外,還支持GIF格式圖片以及視頻縮略圖的顯示。

  1. Glide.with(this) 
  2.         .load("圖片地址:url或path") 
  3.         .placeholder(R.mipmap.ic_launcher) 
  4.         .error(R.mipmap.ic_launcher) 
  5.         .override(100,100)//此處與Picasso不一樣 
  6.         .centerCrop() 
  7.         .fitCenter()//此處與Picasso不一樣 
  8.         .into(imageView); 

 

可見Glide和Picasso有90%的類似度,只是在細節上仍是存在很多區別。

Glide提供了靈活的API可讓開發者方便地替換下載圖片所用的網絡函數庫,默認狀況下,它使用HttpUrlConnection做爲網絡請求模塊,開發者也能夠根據本身項目的實際需求靈活使用Google的Volley或者Square的OkHttp等函數庫進行替換。

Fresco

Fresco是Facebook開源的功能強大的圖片緩存與顯示框架。圖片緩存方案通常有兩級緩存,分別是內存緩存和磁盤緩存。目前最流行的「三級緩存」說法是錯誤的,所謂「網絡緩存」並非Android端所控制的。在Fresco中增長了一級內存緩存,這使得Fresco成了加載大量大圖以後OOM機率最低的圖片緩存與顯示框架。

Fresco無與倫比的加載速度和穩定性讓它在2015年流行過一陣子,但強大的性能是以增長App 3.4M的體積換來的,而且Fresco使用有些複雜,致使了Fresco只適合大型App;而Picasso的功能太少,僅適用於小型App;綜上,通常體量和功能的App建議選擇Glide。

咱們不要拘泥於用開源框架或自定義控件加載圖片,在電商類應用中常見的相似淘寶詳情頁的那種很長很長的圖片的url,建議直接用WebView顯示:

  1. webView.loadUrl("淘寶或微博長長的圖"); 
  2.  
  3. WebSettings webSettings = webView.getSettings(); 
  4. webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); 
  5. webSettings.setJavaScriptEnabled(true); 
  6.  
  7. webView.setWebViewClient(new WebViewClient() { 
  8.     @Override 
  9.     public void onPageFinished(WebView view, String url) { 
  10.         super.onPageFinished(view, url); 
  11.         String javascript = "javascript:function ResizeImages() {" + 
  12.                 "var myimg,oldwidth;" + 
  13.                 "var maxwidth = document.body.clientWidth;" + 
  14.                 "for(i=0;i <document.images.length;i++){" + 
  15.                 "myimg = document.images[i];" + 
  16.                 "if(myimg.width > maxwidth){" + 
  17.                 "oldwidth = myimg.width;" + 
  18.                 "myimg.width = maxwidth;" + 
  19.                 "}" + 
  20.                 "}" + 
  21.                 "}"; 
  22.         view.loadUrl(javascript); 
  23.         view.loadUrl("javascript:ResizeImages();"); 
  24.     } 
  25. }); 

 

3、數據庫操做

Android的數據庫是基於開源的SQLite實現的,適用於保存大量數據,不過和上文的JavaScript代碼同樣,SQL代碼也是用String形式的,因此IDE沒有自動糾錯和代碼補全功能,這就意味着咱們須要一個不用寫複雜的sql語句,而用簡單的API便可完成建立和操縱數據的數據庫操做框架。

ORMLite

ORMLite是目前使用人數最多的數據庫操做框架,儘管在2013就已經中止維護,但由於操做簡便仍然廣受歡迎。

SugarORM

SugarORM是一個較冷門的數據庫操做框架,性能暫且不論,單憑每次增長列必須在assests裏新建一個SQL文件就夠讓人頭疼了。

GreenDAO

GreenDAO是一個輕量級且快速的ORM框架,專門爲Android高度優化和定製,它可以支持每秒數千條記錄的CRUD操做。儘管讀寫速度是ORMLite的4倍,但複雜的學習過程和操做方式卻使人望而卻步。

Realm

Realm並非一個基於SQLite的數據庫框架,而是一個自有數據庫引擎,而且帶有數據庫可視化操做工具的整套數據庫操做解決方案。

Realm有一個顯著的優勢是跨平臺,Android和iOS開發者無需考慮內部數據的架構,調用Realm提供的API便可輕鬆完成數據的交換。其次Realm爲開發者提供了一個輕量級的數據庫可視化操做工具,保證了開發者能夠輕鬆查看數據庫中的內容,並實現簡單地插入和刪除等操做。

Realm的速度也比其餘框架快得多,不過Realm的體積高達4.2MB,通常項目可能沒法接受。

【小結】綜合性能考慮,包大小以及開源庫的可持續發展等因素,建議對數據庫要求較高的 App採用GreenDAO,對數據要求極其嚴格的App採用Realm,而通常的App採用ORMLite,畢竟編程效率纔是王道。

4、JSON解析與生成

移動互聯網產品與服務器端通訊的數據格式,若是沒有特殊需求的話,通常都使用JSON格式。Android系統也原生的提供了JSON解析的API,可是速度很是慢,並且沒有提供簡潔方便的接口來提升開發者的效率和下降出錯的可能。

Gson

Gosn是Google出品的JSON解析函數庫,能夠將JSON字符串反序列化對應的Java對象,或者反過來將Java對象序列化爲對應的JSON字符串,免去了開發者手動經過JSONObject和JSONArray將JSON字段逐個進行解析的煩惱,也減小了出錯的可能性,加強了代碼的質量。使用Gson解析時,對應的Java實體類無需使用註解進行標記,支持任意複雜Java對象包括沒有源代碼的對象。

  1. GsonPlayer gsonPlayer = new Gson() 
  2.         .fromJson("{\"age\":0,\"name\":\"姓名\"}" 
  3.                 ,GsonPlayer.class); 

 

上文提到的數據庫框架適合存儲大量數據,而存儲少許數據時則能夠用SharedPreferences保存JSON的形式:

  1. List list = new ArrayList(); 
  2. for (int i=0;i<10;i++){ 
  3.     Map map = new HashMap(); 
  4.     map.put("age",i); 
  5.     map.put("name",""+i); 
  6.     list.add(map); 
  7. String JSON = new Gson().toJson(list); 

 

Jackson

Jackson是Java語言的一個流行的JSON函數庫,並無爲Android優化定製過,所以函數保重包含不少非必要的API,用於Android平臺會更顯著的增大最終生成的APK的體積。

Fastjson

Fastjson是阿里巴巴出品的一個Java語言編寫的高性能且功能完善的JSON函數庫。它採用一種「假定有序快速匹配」的算法,號稱是目前Java語言中最快的JSON庫。Fastjson還存在一個專門爲Android定製的版本,和標準版本相比,Android版本去掉了一些Dalvik不支持的功能,使得jar包更小。

  1. FastjsonPlayer fastjsonPlayer  = JSON 
  2.         .parseObject("{\"age\":0,\"name\":\"姓名\"}" 
  3.                 ,FastjsonPlayer.class); 

 

【小結】在解析長JSON時Fastjson有明顯的速度優點,但解析普通長度的JSON時Gson卻略勝一籌。從速度、體積、文檔和技術支持、官方推薦等方面綜合考慮,Gson毫無疑問是最佳選擇。

5、組件間通訊

Android中Activity、Service、Fragment等組件以及不一樣進程之間的相互通訊主要有Broadcast和Handler兩種方法,但這些方法都比較繁瑣。事件總線是一種比較簡便的方法,其基本原理是發送者把消息發送到事件總線,而後事件總線在接收者中查找哪些方法註冊了這個事件,若是某個方法註冊了這個事件,就觸發該方法。

EventBus

EventBus是專爲一個Android端優化的publish/subscribe消息總線,簡化了應用程序內各組件間、組件與後臺線程間的通訊。用事件總線原理實現組件間通訊可能會形成性能問題:EventBus在發佈Event的時候就要作好準備可能並無人接受這個Event, Subscribe的時候也要作好準備可能永遠不會收到Event。Event不管順序仍是時間上都某種程度上不太可控。咱們能夠利用響應式編程來解決這個問題。

RxJava

RxJava是一個在 JVM 上使用可觀測的序列來組成異步的、基於事件的程序的響應式編程框架。若是一個訂閱者須要註冊多個事件的時候,Rxjava須要一個個單獨的註冊,而EventBus則能夠實現一個訂閱者訂閱多個事件,和一個事件對應多個訂閱者。顯然RxJava的性能更好,但EventBus操做更簡便。

【小結】組件間通訊框架還有Otto和Guava等許多種,但都在某些方面稍有欠缺,所以咱們技術選型的範圍就在EventBus和RxJava之間,建議小型App選擇EventBus,體量中等以上的App選擇RxJava或RxAndroid。

6、依賴注入

所謂依賴注入,就是目標類(目標類須要進行依賴初始化的類(JavaBean))中所依賴的其餘的類的初始化過程,不是經過手動編碼的方式建立(findViewById等),而是經過技術手段(註解和反射等)能夠把其餘的類的已經初始化好的實例自動注入到目標類中。

AndroidAnnotations

AndroidAnnotations是功能最豐富的依賴注入框架,但存在體積過於龐大、與其餘利用註解的框架有衝突、輸出太多logcat、須要生成一個以「_」結尾的新類都是與追求編程效率的初衷相違背的。

ButterKnife

ButterKnife具有AndroidAnnotations的大多數主要功能,而且使用簡便,這是ButterKnife在Activity中的使用:

  1. public class ButterKnifeActivity extends AppCompatActivity { 
  2.  
  3.     private Unbinder unbinder; 
  4.     @BindString(R.string.str_butter_knife) 
  5.     String butterKnifeStr; 
  6.     @BindDrawable(R.mipmap.ic_launcher) 
  7.     Drawable butterKnifeDrawable; 
  8.     @BindView(R.id.iv_butter_knife) 
  9.     ImageView butterKnifeIv; 
  10.  
  11.     @Override 
  12.     protected void onCreate(Bundle savedInstanceState) { 
  13.         super.onCreate(savedInstanceState); 
  14.         setContentView(R.layout.activity_butter_knife); 
  15.         unbinder = ButterKnife.bind(this); 
  16.  
  17.         butterKnifeIv.setImageDrawable(butterKnifeDrawable); 
  18.     } 
  19.  
  20.     @OnClick(R.id.btn_butter_knife) 
  21.     public void onButterKnifeBtnClick(View view) { 
  22.         Toast.makeText(this,butterKnifeStr,Toast.LENGTH_SHORT).show(); 
  23.     } 
  24.  
  25.     @Override 
  26.     protected void onDestroy() { 
  27.         super.onDestroy(); 
  28.         unbinder.unbind(); 
  29.     } 
  30.      

 

ButterKnife能加強代碼的可讀性,提升編程效率,但若是你用Android Studio搜索Android ButterKnife Zelezny插件後,你會發現寫以上代碼也是浪費時間之舉,由於這些都能自動實現。

【小結】AndroidAnnotations和ButterKnife都是犧牲運行性能換取開發速度的工具,體積龐大的AndroidAnnotations對compile速度較大,而ButterKnife對runtime性能的影響略大於AndroidAnnotations。綜合考慮以後,爲了寫出更高質量的代碼,也爲了debug更簡便,我選擇了ButterKnife。

【寫在最後】

上述Android開源框架的合理利用能加快開發進度,也能提升代碼可維護性。除了上述幾大框架,Android開源框架還有多媒體、文件I/O、動畫等多個大類,合理運用開源框架提升編程效率節省下來的時間能夠用於讀書、健身或陪陪本身的另外一半,早日成爲人生贏家。

歡迎掃碼加羣學習

 

51CTO開發者交流羣④羣 627843829

【51CTO原創稿件,合做站點轉載請註明原文做者和出處爲51CTO.com】

相關文章
相關標籤/搜索