android 多線程編程
android 中的線程是基於 linux 的線程,當我們啟動一個App的時候,Android系統會啟動一個Linux Process,該Process包含一個Thread,稱為UI Thread或Main Thread。
我們一個 activity 中添加兩個 button 和 textview,button 用於控制啟動和停止線程,textview用於接收線程返回值,用於查看線程是如何更新視圖,也就是後台線程或叫做工作線程是如何與主線程通訊的。我現在做一個最簡單的示例。代碼如下。這裡列印的線程為主線程的 id。
經過一段時間我們應用就崩潰了,這是應列印阻塞UI線程其他邏輯的執行,從而導致界面卡頓。如果卡頓時間超過5秒,系統就會報ANR錯誤。所以,如果要執行耗時的操作,我們需要另起線程執行。
然後我們讓代碼運行在一個我們新創建的線程,代碼如下,再看一看效果,
好了我們已經成功解決上一個問題,我們接下來要做的事。我們如何把處理結果放回到主線程,更新線程的UI。
我們通過 handler 對象
總結一下
Android 是如何處理線程間通信的,
Message 或 Runnable 對象:這些對象在線程間傳遞,通過他們實現通信。
MessageQueque: 消息隊列,是 Message 和 Runnable 的容器,他們都是按一定順序存放在消息隊列中,依次被處理
Looper :負責Message 和 Runnable 對象,分發給相應的 Handler 對象。
Hander 即是 Message 和 Runnable 對象的來源,也就是說他將對象發送給 MessageQueque 同時也是 Looper 對象的接收器,Looper 會把 Message 和 Runnable 發送給 Handler
並且在從 Looper 接受後執行 Message 和 Runnable 發送操作在發送線程中完成,而執行操作在接收線程中完成,來實現不同線程的通訊。
AsyncTask是android提供的輕量級的非同步類,可以直接繼承AsyncTask,在類中實現非同步操作,並提供介面反饋當前非同步執行的程度(可以通過介面實現UI進度更新),最後反饋執行的結果給UI主線程。
AsyncTask 不是線程框架,只是一個用於工作線程和主線程之間通訊的通訊類。其中 doInBackground 是抽象方法,doPreExecute,onProgressUpdate, onPostExecute, onCancelled 還好理解,大家可以自己做些功課
這裡重點說一下 Executor 每次 AsyncTask 要被執行時,都必須提供一個 Executor 對象。啟動 AsyncTask 有三種方式
1. execute(params): 將任務添加到 SERIAL_EXECUTOR 隊列中。
2. execute(Runnable) 這是靜態方法,用於執行 Runnable 對象
3. executeOnExecutor(Executor, Params) 通過此方法可以指定 Executor。
AsyncTask通過一個阻塞隊列BlockingQuery存儲待執行的任務,利用靜態線程池THREAD_POOL_EXECUTOR提供一定數量的線程,默認128個。在Android 3.0以前,默認採取的是並行任務執行器,3.0以後改成了默認採用串列任務執行器,通過靜態串列任務執行器SERIAL_EXECUTOR控制任務串列執行,循環取出任務交給THREAD_POOL_EXECUTOR中的線程執行,執行完一個,再執行下一個。
我們嘗試自己實現一個 looper 和 Handler。我們在 Thread.run() 中調用靜態方法 Looper.prepare() 來指定一個 Looper 對象,創建一個MessageQueue(消息隊列),為了 Looper 分發 Message 和 Runnable 給 Handler。
創建一個線程,然後任務發送到消息隊列messageQueue
我們來任務發送 Runnable 對象,工作進程中執行完的任務更新到主線線程中更新 UI。
今天到這裡吧
TAG:小馬學編程 |