目前 Android 開發,從廣義上來講能夠劃爲前端的一部分,畢竟大部分 Android 開發所作的工做就是從服務器獲取數據,將這些數據用合適的方式展現給用戶,再把用戶操做產生的數據傳遞給服務器。在這樣的情境下 Android 開發所須要解決的一個核心問題就是數據的傳遞,如何把服務器與頁面內容關聯起來,而且保持同步。相信對於這一過程,每個工程師都有本身的解決方案。這一個過程看似簡單,但真正想要將其比較完美的實現,卻也須要花費一番功夫。前端
蠻荒時代數據庫
在 Android 開發還未成熟,處於蠻荒時期的時候,沒有成型方案做爲參考,此時比較常見的作法就是在 Activity 裏建立線程,在線程內發送網絡請求,以後用 Handler 把請求結果傳遞到主線程,主線程收到信息後更新頁面,這種方式缺陷是十分明顯的,它會形成 Activity 十分臃腫,隨着項目的發展會變成一團亂麻。編程
網絡庫緩存
後來出現了諸多成型的網絡的封裝庫,所以網絡請求的核心邏輯就不在 Activity 中了,這爲 Activity 減輕了很多負擔,可是此時又一個問題出現了,那就是如何從請求庫獲取網絡請求的返回結果,此時大多數網絡庫都採用了一個最容易想到的方案,那就是 Callback,Activity 發出請求時會獲得一個 Callback,並通 Callback 回調獲得最終的網絡請求結果。安全
數據層服務器
可是網絡請求問題解決了,可是很快另外一個問題又成了比較困擾的內容,例如:網絡請求獲得的結果並不能直接使用,須要進行一些數據的轉換,又或者網絡請求並不需過高的實時性,請求一次後須要緩存起來,避免屢次重複請求。這樣在 Activity 中就須要一些數據轉換操做,或者進行一些數據庫相關的操做,很快 Activity 又會變得臃腫起來。網絡
爲了不在 Activity 中直接進行這些操做而變得臃腫,不少人不得不在網絡請求和 Activity 之間封裝一個數據層,Activity 向數據層請求數據,數據層根據須要從網絡或者數據庫獲取數據而且對數據進行轉換,而後交給 Activity。此時數據須要如何傳遞呢?spa
Activity <--callbac-1-- 數據層 <--callback-2-- 網絡請求
複製代碼
一般來講須要 Activity 向數據層發送請求時附帶一個 Callback,而數據層直接向網絡發出請求時又是另一個 Callback,須要把數據從一個 Callback 傳遞到另外一 Callback,固然這是對於一些比較簡單的業務,若是業務更加複雜一點,可能會劃分更多的層和節點,那麼就不只僅是兩個 Callback 了,數據須要多在多個 Callback 之間流動,Callback 太多就會致使邏輯不是那麼清晰,當項目大到必定程度時,裏面的各類 Callback 就能把人繞暈。線程
EventBus設計
爲了解決錯綜複雜的 Callback 問題,EventBus 誕生了,它的核心其實就是發佈訂閱模式,當 Activity 須要獲取一些信息時,發送一個事件(Event), 數據層接收到 Event 後執行相關操做,以後一樣經過發送 Event 告訴 Activity 最終的結果。此時各個組件之間不須要再去關心各類錯中複雜的數據傳遞方式,只須要把須要傳遞的數據包裝成一個個的 Event 再經過 EventBus 發送出去,若是須要相關的事件的話,就在合適的位置註冊一下監聽該事件。
所謂事件總線,就是把全部的事件都經過一個地方進行傳遞,這個和計算機硬件上的總線原理相似,所以也就被稱爲「事件總線」,在我最初接觸到這種思想時,確實也被驚豔了一下,這種方式在必定程度上解決了過多 Callback 的問題,讓代碼看起來更加簡潔了。
可是這種方式也並非天衣無縫的,它的確讓代碼更加簡潔了,可是它將數據傳遞的過程隱藏起來了,至關於切斷了數據流的追蹤線路,增大了數據流追蹤的難度,若是整個項目都是本身設計或者一開始就參與的問題卻是不大,可是若是是接手別人的項目是這樣設計的,那麼接手的人極可能會一臉懵逼。
例如:我須要當前的用戶的信息,也知道經過哪一個 Event 來接收這一信息,可是我發現接收到的信息有時是錯誤的,所以我須要找到發送該信息的位置並修改這一錯誤,這時就比較麻煩了,由於全部信息都是經過 EventBus 發送的,但我沒法經過 EventBus 直接追蹤到發送位置,所以我須要找到該 Event ,並追蹤這個 Event 都被哪些地方使用了,而後從這些地方中篩選出時哪裏發送了這個錯誤信息,對於一個龐大的項目來講,這一工做量無疑是巨大的,倘若前人在多個地方都發送了這一個 Event,我則須要對全部發送過這個 Event 的地方都進行檢查,這會浪費大量的工做時間。所以在實際的公司項目上我不多采用 EventBus 這一方案,儘管它很好用,可是這一點缺陷就足以至命。
數據流
正在我糾結到底如何傳遞數據時,Rx 技術方案就出如今了個人面前,Rx 的核心思想就是響應式編程,即一種面向數據流和變化傳播的編程範式,數據更新是相關聯的。 這種思想和 Linux 中的管道也是相似的,數據從一個地方進入轉換後輸出,而這個輸出剛好是另外一段處理的輸入,就這樣把數據串聯起來。
這是一個簡單的例子,將一個空白的圓經過兩步轉換變成咱們所須要的樣子,數據從一個位置流向另外一個位置,並不斷的變化。
Rx 核心之一就是數據流,包括 Java8 中也有引入相似的流式思想。
響應式這一思想並不算特別新穎,不過是這種思想近些年才被人用代碼實現出來具有了商用能力而已,隨着 RxJava 技術的成熟,目前我參與的項目中全部的數據獲取基本都是經過 RxJava 進行處理的。而且基於 RxJava 提供的強大操做符和線程調度能力,確實也算解決了一大難題。
相比於 EventBus 這種形式,這種方案最重要的仍是數據流的可追蹤性,仍是上面的例子,若是我發現了最終的結果有錯誤,那麼我只須要跟隨着這條數據鏈不斷的向上追蹤,並逐一環節的進行檢查便可,很快就能找到問題的根源所在。就目前而言,這種方式仍是不錯的,尤爲是配合 Java8 的一些新特性使用,至關爽快。
若是想要了解這一思想的運用方式,我的推薦看 《RxJava的官方文檔》和 《Java8 實戰》,看完這些基本就能夠理解響應式編程中數據流這一思想了。
LiveData
LiveData 是 Google 最近推出的一種技術方案,它須要配合 Lifecycle 來使用,它解決的問題核心不是數據傳輸的問題,而是生命週期。咱們都知道網絡傳輸是比較慢的,並且具備不肯定性,所以 Android 不容許其在主線程中執行,必須另開線程,在線程中得到結果後經過一些方式將結果告訴主線程,主線程並根據這些信息進行更新,正是由於網絡返回時間的不肯定性致使了一個問題的發生,當網絡結果返回時,可能須要這一結果的頁面已經不存在了。
例如:在我打開一個 activity 時發起了一個網絡,網絡請求的結果會更新 activity 裏面的內容,可是在我發起請求後我不想要這個結果了,直接點擊返回鍵把 activity 關閉了,若是我在關閉 activity 時忘記了取消此次網絡請求,那麼它在一段時間後就可能會返回結果,並在返回結果裏面嘗試去更新一些已經被銷燬的 View,就會產生異常,致使程序崩潰。
爲了不這些問題的出現咱們不得不在代碼裏面添加不少安全檢查,每當有相似的狀況出現都須要安全檢查,因而核心的業務邏輯就可能被淹沒在了諸多的安全檢查中。
爲了解決這一問題,Lifecycle 和 LiveData 就出現了,其實在 Lifecycle 出現以前,就有采用相似思想的技術方案出現,可是 Lifecycle 是 Google 官方推出的內容,在 support 包裏面的不少組件已經默認支持了 Lifecycle,所以使用 Lifecycle 和 LiveData 會更加的簡便。
在引入的 LiveData 後,基本的項目結構就變成下面這樣了:
這只是一個簡略的結構,在實際的項目中使用時確定是比這個要複雜的,須要根據具體的業務需求選擇不一樣的技術方案。
在通過上述的幾回演變後,Activity 的工做量大大的減輕了,網絡、數據庫、一部分安全檢查邏輯都被從 Activity 中移除了,Activity 只須要綁定一下 View,並控制一下顯示內容就能夠了,所以會看起來特別的簡潔,若是配合 Butterknife 和 Dagger2 來使用的話,會更加簡潔,不過這兩個內容並不在本文的討論範圍內,所以也就不展開敘述了。
以上提到的相關技術,並無詳細的說明,若比較感興趣,能夠本身查詢關鍵詞去詳細的瞭解一下。