Android運行后臺任務的時候需要考慮的事情
當你開始開發Android應用的時候,想通過跟服務器交互并且通過API去獲取數據,然后將數據保存到本地的數據庫,在你運行app執行任務的時候,會獲取到一個 NetworkOnMainThreadException 的異常,或者當你在左一些繁重的計算工作的時候,你會得到一個討厭的ANR彈出框,接著你的app就崩潰了,對于開發者來說這是最糟糕的一個噩夢,一個簡單的解決這些的辦法就是-工作線程。
屏幕上的任何東西對用戶來說都是可見的,都是發生在主線程或者是UI線程,每一個不直接影響UI的都應該在工作線程完成,Android提供了許多API來實現這個功能并且很多第三方的庫也可以簡化這些工作。
這篇文章不是如何實現線程工作的一個指導,網絡上已經有大量的相關的指導文章,本文重點介紹各種線程機制的優缺點,并且幫助你去選擇哪一個。
Thread
線程是最直接和最終的方案,其他方案提供了一個線程的包裝類,JVM允許不同的線程并發運行,所以我們可以創建自己的工作線程并且在不阻塞主線程的情況下執行任務。
優點
- 易于實現并且很容易啟動
- ThreadPool 和 Executor 可以很容易的為任務排列優先級并且加入隊列
- Handler 和 looper 可以用于線程和activity之間的交流
- 所有其他第三方庫或幫助程序類在它的核心線程。
缺點
- 他是非常基本的,不利于復雜的任務
- 許多事情需要考慮像Activity這樣的生命周期
- 如果在Activity中直接用作匿名內部類的話,會因為hard引用而導致內存泄露
- UI與線程之間的交互不可能完成,需要使用handler來完成交互工作。
AsyncTask
AsyncTask是一個android類,在其中有一個工作線程實現,我們可以直接使用它并且免去了自己創建工作線程的麻煩。
優點
- 使用起來簡單直接,并且只用覆蓋一個方法。
- 靜態方法 AsyncTask.execute() 使用起來更簡單
- 不像Threads,AsyncTask提供了一些回調方法 onPreExecute , onProgressUpdate , onPostExecute 來分別通知任務在主線程運行時的開啟,更新和完成。
缺點
- 執行互相關的任務的時候會產生回調地獄
- 默認情況下,以串行方式執行任務,如果需要并行操作,需要執行 executeOnExecutor()
- AsyncTask的一個實例只能執行一次任務,如果你想再次執行的話那么需要創建新的實例。
Service
Service用于執行長時間的運行任務,他可以從app訪問并且用于進程間通信,服務本身不在工作線程執行任務,如果你需要的話,可以在Service中創建自己的工作線程。
IntentService
IntentService是一個內部包含工作線程的Service,他可以用于對不同的數據集執行相同的任務,如果你需要播放音樂或者下載數據的話,那么IntentService就是一個很好的選擇,他可以作為STICKY啟動,并且僅在任務完成后終止,而不是在activity被銷毀時終止。
優點
- 直接實現,簡單
- Handler 和 LocalBroadcastManager 可以用于線程間通信(UI和工作線程)。
- 所有的應用程序都可用,并且可以用于不同的進程
- 在關閉應用程序之后還可以執行任務
- 比activity有更高的優先級,所以在后臺被終止的機會很小。
缺點
- 屏幕方向改變或者是配置改變的時候無法生存
- 任務排隊并連續執行
- 默認情況下不能與主線程交互
Loader
Loader是更好的線程實現,有助于管理線程對fragment和activity的生命周期。
優點
- 通過回調簡化線程管理,像 onCreateLoader , onLoaderFinished , onLoadReset .
- 可以通過緩存數據來維持方向改變或者配置改變后任務的繼續。
- 可以實現可觀察數據以主動監聽變化
- Android提供了不同的加載器子類, CursorLoader , AsyncTaskLoader 更易于使用。
缺點
- 依賴Activity或者Fragment的生命周期,因此會隨著Activity和Fragment銷毀
- 不保證完成
- 需要在Activity/Fragment中實現,指定加載程序要實現的數據類型。
JobService和JobScheduler
JobService和JobScheduler是在Api21之后引入的,以便更好的控制任務的執行,假設你有很多的后臺任務,如同服務器的數據同步,可能要消耗大量的電量電池電量和網絡流量,當設備正在充電/連接wifi時,你如果要執行這么長時間的廣泛的任務的話,那么這個是絕對能夠給你幫助的。
優點
- 可以將批處理一起提高性能
- 如前所述,可以定義任務運行的有利狀態
- 設備重新啟動
缺點
- 如果任務是時間敏感的,因為不能滿足確切的條件,則不是有利的
- 相對新的API只支持從Lollipop。
RxJava
如果你熟悉函數式編程,那么你可能聽說過RxJava,他是響應式方法的JVM實現,與RxAndroid一起,他為后臺進程和主線程間的通信提供了最簡單的API,還提供了流式編碼。
優點
- 很容易定義在哪個線程執行任務,在哪個線程處理結果,只需要分別定義 subscribeOn 和 observableOn 。
- 為后臺線程提供助手線程,如 Scheduler.io() , Schedulers.newThread() 和 Schedulers.computation() ;
- 有一個直接的方式來訪問主線程,只需使用 AndroidSchedulers.mainThread() 。
- 可以順序執行任務,并行,并發結果等
- 更容易處理異常。
- 沒有回調地獄:)
缺點
- 陡峭的學習曲線
- 調試起來更困難
來自:https://blog.yipl.com.np/things-to-consider-before-running-background-tasks-e71f00d2ad3a#.5w12odqj3