Android(安卓)多線程原理理解

為什么我們需要使用多線程

  • 提高用戶體驗

  • 避免ANR(Application is not responding)

上面這兩個原因其實也是因果關系,因為會出現ANR,所以會導致用戶體驗很差


詳解ANR

安卓的main線程負責UI的繪制,為了防止應用程序反應較慢導致系統無法正常用運行做如下處理:
  • 當用戶輸入時間在5秒內無法得到響應,那么系統會彈出ANR對話框
  • BreadcastReciever 超過10秒沒執行完也會彈出ANR對話
所以事件處理的原則:

所有可能耗時的操作都放到其他線程去處理


為什么要在android中使用多線程

異步操作

應用中有些情況下并不一定需要同步阻塞去等待返回結果,可以通過多線程來實現異步
舉例說明:假如某個Activity需要從云端獲取一些圖片,加載圖片比較耗時,是一個耗時的操作,這時需要使用異步加載,加載完成一個圖片刷新一個


主線程Activity與子線程

  • 默認啟動的第一個Activity成為主線程
  • 由此Activity創建的線程(子線程)無法對主線程控制的內容進行修改,如果強行修改,會報以下錯誤:
    Only the original thread that created a view hierarchy can touch its views.
  • 所以只有UI線程才能更新UI

所以怎么解決跨線程更新UI呢?

  • 方式一:其他線程委托UI線程更新UI
  • 方式二:通過Hnadler發送Message給UI線程,令UI線程根據Message消息更新UI
  • 方式三:使用Android提供的AsyncTask

點擊5分鐘完全理解android handler

通常情況下,我們會使用方式二和方式三來解決更新UI的問題

但是Thread + Handler 是有一定的缺陷的

  • 線程的開銷較大,如果每個任務都要創建一個線程,那么程序的效率要低很多。
  • 線程無法管理,匿名線程創建并啟動后就不受程序的控制了,如果有很多個請求發送,那么就會啟動非常多的線程,系統將不堪重負。
  • 另外,在新線程中更新UI還必須要引入handler,這讓代碼看上去非常臃腫。

所以這里就引入了AsyncTask

AsyncTask的特點:

在任務在主UI線程之外運行,而回調方法是在主UI線程中,這就有 效地避免了使用Handler帶來的麻煩。

AsyncTask定義了三種泛型類型:

  • Params : 啟動任務執行的輸入參數。
  • Progress : 后臺任務執行的百分比。
  • Result : 后臺執行任務返回的結果。

使用AsyncTask簡化多線程開發:

AsyncTask專門用于完成非UI線程更新UI的任務
本質上也是開啟新線程執行耗時操作,然后將結果發送給UI線程 優點:簡化代碼,減少編寫線程間通信代碼這一繁瑣且易出錯的過程

操作要點:

AsyncTask為抽象類,必須先子類化

  1. onPreExecute():開始執行前的準備工作
  2. doInBackground(Params ...):開始執行后臺處理,并調用publishProgress(Progress )方法來更新實時的任務進度
  3. onProgressUpdate(Progress ...):在publishProgress()方法被調用
    后,UI線程將調 用這個方法從而在界面上展示任務的進展情況
  4. onPostExecute(Result...):執行完成后的操作,傳送結果給UI線程

幾條必須遵守和記住的原則:

  1. Task的實例必須在UI 線程中創建
  1. execute方法必須在UI 線程中調用
  2. 不要手動的調用onPreExecute(),
    onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...) 這幾個方法,它們需要在UI線程中實例化這個task來調用。
  3. 該task只能被執行一次,否則多次調用時將會出現異常
    doInBackground方法和onPostExecute的參數必須對應,這兩個參數在AsyncTask聲 明的泛型參數列表中指定,第一個為doInBackground接受的參數,第二個為顯示進度 的參數,第三個為doInBackground返回和onPostExecute傳入的參數。

構造函數解讀

private class task extends AsyncTask<String, String, String>
AsyncTask<>的參數類型由用戶設定,這里設為三個String

  • 第一個String代表輸入到任務的參數類型,也即是doInBackground()的參數類型
  • 第二個String代表處理過程中的參數類型,也就是doInBackground()執行過程中的產出 參數類型,通過publishProgress()發消息,傳遞給onProgressUpdate()一般用來更新界 面
  • 第三個String代表任務結束的產出類型,也就是doInBackground()的返回值類型,和 onPostExecute()的參數類型
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容