Android异步编程
目錄:
- Android的線程和內存模型
- AsyncTask
- 碎片化問題
- Activity生命周期問題
- Handler & HandlerThread
- Looper
- Loader
- AsyncTaskLoader
- CursorLoader
- IntentService
- Service
- AlarmManager
- 參考鏈接
Android的線程和內存模型
Android操作系統在boot后,會啟動一個Zygote(受精卵)進程,Zygote進程負責創建大部分應用程序進程。Zygote進程啟動加載核心程序庫和數據結構到內存后會創建一個Dalvik虛擬機(DVM)進程--SystemServer,此進程會包含大部分的系統服務(包括管理Activity的服務ActivityManagerService),SystemServer初始化后,Zygote進程會偵聽本地的socket端口, 等待進一步的指令。當新的app被啟動時,Zygote會為這個app創建一個DVM—-直接fork出一個子進程,這種架構的好處是同時啟動多個App時,多個App進程可以訪問共享內存。
Android App的進程也是一個DVM,內部有許多線程在執行,比如,主UI線程(Main Thread),垃圾回收線程等。其中主UI線程負責執行我們寫的應用代碼。對于只做很少的I/O操作或耗時操作的App,單一線程開發模式問題不大,但是如果有大量IO或者CPU計算的任務,我們就必須在其他線程內完成了。
因為主UI線程需要根據硬件刷新率[^3]同步用戶界面的重繪。手機應用體驗流暢要求界面幀率[^3]達到每秒60,也就是說每16.67毫秒就需要重繪一幀,這意味著如果我們在主線程上執行的任務超過16毫秒,就會出現丟幀現象,也就是界面會開始變卡。。。
Android異步執行任務的方法有以下幾種:
AsyncTask
AsyncTask是最常用的異步方法,功能結構設計的也很豐富,給使用者足夠的控制,使用上主要是將異步執行的任務放在下面方法里。
然后調用.execute(params)方法即可。
AsyncTask的執行邏輯在API Level 3只能串行執行, 在API Level 4改成了最多128個線程的線程池執行,API Level 11則改成了缺省所有的AsyncTask是在一個線程中順序執行的,這樣可以保證執行和提交的次序一致,如果希望能并發的執行,可以用下面的方法在線程池內執行:
AsyncTask.THREAD_POOL_EXECUTOR是ThreadPoolExecutor的一個實例,配置是最少5個線程,最多128個。如果需要自己來配置線程池大小,你可以傳遞自己配置的一個實例到上述方法。
使用AsyncTask需要注意的幾個問題:
碎片化問題
因為不同版本的Android AsyncTask缺省執行邏輯并不一樣,可能在不同機型上表現不一致。如果要自己控制AsyncTask的并發度,解決這個問題的建議是復制Android SDK的AsyncTask源碼自己實現一個AsyncTask。
Activity生命周期問題
Activity可能早于AsyncTask執行完被銷毀,如果AsyncTask還繼續執行,有可能會浪費資源,并且如果AsyncTask里引用了Activity或部分的View Hierarchy,還會造成引用的對象不會被垃圾回收而引起內存泄漏。通常AsyncTask會定義為Activity的一個匿名inner class,這會建立一個隱式的引用到Activity。
解決的方法是:
Async比較合適的是較短的(1,2秒),CPU密集計算或讀寫文件等阻塞IO操作。耗時較長的網絡調用用Async不是最合適的。
Handler & HandlerThread
Handler的異步編程是基于消息隊列模型的。執行任務的線程稱之為Looper線程,其他線程則將需要異步執行的任務發送給Looper線程–插入其消息隊列,方法有:post(較方便使用,但每次需要創建新對象)或sendMessage(較高效,復用消息實例,適合執行大量類似的異步任務)
Looper
Looper和它的名字意思一樣就是Looper線程會永遠循環,當沒有消息的時候,Looper線程(消費者)會使用(Object.wait)方法等待其他線程(生產者)插入新的任務消息,這時候其他線程(Object.notify)
Android的主線程其實就是一個Looper線程。
需要注意的是,使用Handler和AsyncTask一樣,要注意匿名inner class對Activity的隱式引用而造成內存泄漏,所以使用的時候要記得清理;
解決方法是使用對使用的Activity中的View對象用Weak Reference,并處理當View對象為null的情況。
Handler適合更長一點的(>2秒)的異步任務處理。
Loader
Loader在Android編程框架中被廣泛用于后臺加載數據(從文件,數據庫甚至網絡)。
AsyncTaskLoader
具體的Loader實現。
CursorLoader
用戶數據庫數據后臺加載。
Loader在使用上比較大的優勢是和Activity的部分解耦,更見到的生命周期管理。
IntentService
IntentService是Service的一個實現類。其內部實現包含了一個HandlerThread,當任務提交給IntentService時,會被加到隊列并順序處理。
IntentService返回任務結果給Activity可以有下面幾種方法(Service和Activity的通信方法):
IntentService可以完全和Activity解耦。適合即使App主界面退出情況下也必須完成的任務,比如后臺上傳日志,圖片之類的任務。
Service
Service合適執行獨立于任何Activity或Fragment的任務,即使App主界面退出情況下也必須完成的任務;或者需要比IntentService更高或更細致的并發控制。
AlarmManager
AlarmManager可以不在人工干預下定時執行任務,比如定時檢查郵件,下載更新,或同步內容到云端。
參考鏈接
原文地址:http://hugozhu.myalert.info/2014/06/29/46-async-android.html
總結
以上是生活随笔為你收集整理的Android异步编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解 Android 的 IPC 机
- 下一篇: Android MediaRecorde