什么是AsyncTask
AsyncTask是Android提供的輕量級的異步類, 可以直接繼承AsyncTask,在類中實現(xiàn)異步操作,并提供接口反饋當(dāng)前異步執(zhí)行進度(可以通過接口實現(xiàn)UI進度更新),最后反饋執(zhí)行的結(jié)果給UI主線程。AsyncTask 有兩個線程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一個Handler(InternalHandler), 其中SerialExecutor是用來任務(wù)排隊的 ,而線程池THREAD_POOL_EXECUTOR是用來真正執(zhí)行任務(wù)的;? AsyncTask異步任務(wù)底層是封裝了線程池和Handler 。注意兼容問題: Android 3.0以前 ,默認(rèn)情況下AsyncTask是串行執(zhí)行, 3.0以后才有executeOnExecutor方法;
為什么要用AsyncTask
AsyncTask的優(yōu)點是簡單快捷,缺點則是代碼相對臃腫,在多個任務(wù)同時執(zhí)行時,不易對線程進行精確的控制。除了使用AsyncTask外,還可以使用Handler來實現(xiàn)。比如我做的一些聯(lián)網(wǎng)獲取數(shù)據(jù)的操作,就是用Timer+Handler來實現(xiàn)的(由于使用的Socket和服務(wù)器交互,因此使用Timer來定時,在規(guī)定的時間內(nèi)不響應(yīng)的話視為超時。)但是,AsyncTask不適合進行提別耗時的后臺任務(wù),對于特別耗時的任務(wù)來說,建議使用線程池;
?一個AsyncTask異步任務(wù)的執(zhí)行一般包括以下幾個步驟:
1.execute(Params... params),執(zhí)行一個異步任務(wù),需要我們在代碼中調(diào)用此方法,觸發(fā)異步任務(wù)的執(zhí)行。(執(zhí)行)
2.onPreExecute(),在execute(Params... params)被調(diào)用后立即執(zhí)行,一般用來在執(zhí)行后臺任務(wù)前對UI做一些標(biāo)記。(準(zhǔn)備工作)
3.doInBackground(Params... params),在onPreExecute()完成后立即執(zhí)行,用于執(zhí)行較為費時的操作,此方法將接收輸入?yún)?shù)和返回計算結(jié)果。在執(zhí)行過程中可以調(diào)用publishProgress(Progress... values)來更新進度信息。(主線程中執(zhí)行)
4.onProgressUpdate(Progress... values),在調(diào)用publishProgress(Progress... values)時,此方法被執(zhí)行,直接將進度信息更新到UI組件上。(主線程中執(zhí)行,當(dāng)后臺任務(wù)的執(zhí)行進度發(fā)送改變時此方法會被調(diào)用).
5.onPostExecute(Result result),當(dāng)后臺操作結(jié)束時,此方法將會被調(diào)用,計算結(jié)果將做為參數(shù)傳遞到此方法中,直接將結(jié)果顯示到UI組件上。(異步執(zhí)行后這個方法被調(diào)用)
AsyncTask的使用:
1.我們要獲取總大小totalSize,還有當(dāng)前已下載大小count,由這兩個數(shù)值去計算當(dāng)前的下載進度: count/totalSize (注意要拿float去計算, 不然小數(shù)取整后為0)
2.計算出進度后,調(diào)用publishProgress去推送進度,調(diào)用此函數(shù)后,onProgressUpdate才會回調(diào),并且我們將會在onProressUpdate中設(shè)置進度控件的值。
3.resultData是我們的返回值,返回resultData后,才會在OnPostExecute 中獲取結(jié)果值,并吧結(jié)果值展示到界面中。
4.記得finish時釋放資源.
5.異步任務(wù)的實例必須在UI線程中創(chuàng)建。
6.execute(Params... params)方法必須在UI線程中調(diào)用。
7.不要手動調(diào)用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)這幾個方法。
8.不能在doInBackground(Params... params)中更改UI組件的信息。
9.一個任務(wù)實例只能執(zhí)行一次,如果執(zhí)行第二次將會拋出異常。
線程池:
Android里面,耗時的網(wǎng)絡(luò)操作,都會開子線程,在程序里面直接開過多的線程會消耗過多的資源,使用線程池可以很好的維護程序中的線程資源;線程池是預(yù)先創(chuàng)建線程的一種技術(shù)。
1. 線程池在還沒有任務(wù)到來之前,創(chuàng)建一定數(shù)量的線程,放入空閑隊列中,然后對這些資源進行復(fù)用。
2. 減少頻繁的創(chuàng)建和銷毀對象, 因為頻繁創(chuàng)建和銷毀線程耗資源,就會耗時間.
3.因為有的線程執(zhí)行時間比創(chuàng)建和銷毀一個線程的時間還短;?
線程池中涉及的類:
1. Executor:Java里面線程池的頂級接口。
2. ExecutorService:真正的線程池接口。
3. ScheduledExecutorService:能和Timer/TimerTask類似,解決那些需要任務(wù)重復(fù)執(zhí)行的問題。
4. ThreadPoolExecutor(重點):ExecutorService的默認(rèn)實現(xiàn)。
5. ScheduledThreadPoolExecutor:繼承ThreadPoolExecutor的ScheduledExecutorService接口實現(xiàn),周期性任務(wù)調(diào)度的類實現(xiàn)。
6. Executors:可以一行代碼創(chuàng)建一些常見的線程池
Executors介紹:
1.newSingleThreadExecutor:
創(chuàng)建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當(dāng)于單線程串行執(zhí)行>所有任務(wù)。如果這個唯一的線程因為異常結(jié)束,那么會有一個新的線程來替代它。此線程池>保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。
2.newFixedThreadPool:?
創(chuàng)建固定大小的線程池。每次提交一個任務(wù)就創(chuàng)建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執(zhí)行異常而結(jié)束,那么線程池會補充一個新線程。
3.newCachedThreadPool:
創(chuàng)建一個可緩存的線程池。如果線程池的大小超過了處理任務(wù)所需要的線程, 那么就會回收部分空閑(60秒不執(zhí)行任務(wù))的線程,當(dāng)任務(wù)數(shù)增加時,此線程池又可以智能的添加新線程來處理任務(wù)。此線程池不會對線程池大小做限制,線程池大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小。
4.newScheduledThreadPool:
創(chuàng)建一個大小無限的線程池。此線程池支持定時以及周期性執(zhí)行任務(wù)的需求。
ThreadPoolExecutor介紹:
線程池的寫法:?
AsyncTask和線程池結(jié)合使用:
線程池一般的使用方法: ?Executors.newFixedThreadPool(...).execute(Runnable()) 并發(fā)運行;
參考文獻:
java 線程池ThreadPoolExecutor 如何與 AsyncTask() 組合使用。
《Android藝術(shù)與探究》