詳細解讀AsyncTask的黑暗面以及一種替代方案

基于最新版本的AsyncTask詳細解讀主要是一些AsyncTask的原理解讀,本篇將分析AsyncTask使用的受限部,這里可能會有一些你以前沒注意到的點,同時提供一個替代方案AsyncTaskScheduler。

一些關于AsyncTask的指責

如果搜索關鍵詞"AsyncTask的缺陷",會有很多關于AsyncTask缺陷的文章,很多是基于以下幾個問題,但這些問題真的是AsyncTask自身的問題還是使用不當導致的呢?這真的需要好好分析一下,不能人云亦云,強行甩鍋。

  1. 生命周期和內存泄漏
    "當Activity結束或者退出應用時AsyncTask會一直執(zhí)行doInBackground()方法直到方法執(zhí)行結束,這可能會導致在onPostExecute時view不存在而導致崩潰潰,以及可能的內存泄露"。
    如果退出Activity時AsyncTask扔在執(zhí)行,上面說的的卻會發(fā)生,但這些問題需要由使用者來解決而不是AsyncTask來解決,因為AsyncTask只是執(zhí)行后臺任務,它怎么知道你什么時候要終止,要退出,確定使用Handler時不會出現(xiàn)這樣問題???


    怪我嘍???

    所以應該在相應的生命周期如onDestory調用cancel取消任務,上面的問題就不會發(fā)生了,所有這個鍋不應該AsyncTask來背。

  2. cancel不能正常取消的問題
    首先調用cancel終止AsyncTask的原理是對執(zhí)行異步任務的線程調用interrupt()函數(shù)。
    首先,每個線程內部都有一個boolean型變量表示線程的中斷狀態(tài),true代表線程處于中斷狀態(tài),false表示未處于中斷狀態(tài)。
    而interrupt()方法的作用只是用來改變線程的中斷狀態(tài)(把線程的中斷狀態(tài)改為true,即被中斷)。因此interrupt()方法代表著外界希望中斷此線程,只是希望,具體怎么處理還是線程內部來做,一般情況下interrupt()方法可以使處于阻塞狀態(tài)的線程拋出InterruptedException從而結束阻塞狀態(tài)或則判斷Thread.interrupted()來處理邏輯。所以如果你的AsyncTask后臺任務有未做中斷的處理肯定會一直執(zhí)行這個線程。所以這需要你自己在doInbackground里進行中斷處理,即使你認為這是個缺陷也應該是Thread類的缺陷,因為要用到線程處理異步任務,AsyncTask無法選擇其他方式,而且調用cancel后onPostExecute也不會在執(zhí)行了,不會導致UI線程的問題,所以這個鍋也不應該AsyncTask來背。

  3. Activity意外重啟,狀態(tài)消失問題
    比如當用戶旋轉屏幕的時候Activity就會重新啟動,如果之前有AsyncTask正在異步加載處理數(shù)據,那么之前的數(shù)據就會消失,而新的AsyncTask重新創(chuàng)建,這的卻是個問題,但你用其他的方式進行請求同樣會發(fā)生這個問題啊。

其實可能是我們的要求太多了,AsyncTask只是一個處理異步任務的工具,很多邏輯上的東西需要我們自己來處理,就像使用Handler和Thread,不正確處理同樣會出現(xiàn)上述問題,這些總得來說就是異步帶來的問題,這是一個時間和性能的選擇問題,AsyncTask就是簡化了包裝了Handler的處理步驟而已。上面的這些更應該是一些重要的注意事項,而不是AsyncTask的問題

實際存在的問題

  1. 并行串行問題
    上面的一些可能是由于使用不當導致的,但并行串行問題方面AsyncTask問題很大。
    使用建議

    看AsyncTask源碼文檔時看到這樣建議"AsyncTasks should ideally be used for short operations (a few seconds at the most",就是盡量執(zhí)行一個短時間的任務,最對也就幾秒的任務。當初還很疑惑,AsyncTask這玩意不就是用來處理后臺任務的嗎,又不是在主線程,為什么還限制短時間的任務,那要你何用啊。
    Excuse me ? ? ?

    基于最新版本的AsyncTask詳細解讀分析過在api11后AsyncTask默認的是串行執(zhí)行任務,基本現(xiàn)上市面上的設備上都將是串行執(zhí)行。自己可以寫個Demo試試看。
    這些串行執(zhí)行共用的AsyncTask的是一個線程池,這真的很嚴重。因為是順序執(zhí)行,導致你調用execute() 可能 沒法立刻執(zhí)行,也可能就執(zhí)行不了,因為誰知道有沒有其他的AsyncTask任務在執(zhí)行啊,或者任務還是個很耗時的任務,或者就是個while(ture)循環(huán)或者for(;;)來一直處理一種后臺任務,那么同一進程內的AsyncTask在這之后調用execute的都將無法執(zhí)行。
    想當初初學Android時覺得AsyncTask真是個方便的東西,手機寫了個基于socket通信的應用,doInbackground處理,然后直接通知UI。在doInbackground函數(shù)里處理一些連接以及數(shù)據流的接收及發(fā)送,socket的等待連接和數(shù)據結束都是阻塞的啊,現(xiàn)在回想起來當初真是年輕??。

當然你可以立刻執(zhí)行一個任務通過調用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)通過AsyncTask的THREAD_POOL_EXECUTOR線程池或者傳入其他的線程池來立刻執(zhí)行任務,但THREAD_POOL_EXECUTOR有最大并發(fā)數(shù)的限制,具體分析見基于最新版本的AsyncTask詳細解讀,但只執(zhí)行一個任務時通過線程池來管理的也是無奈之舉,而且這種方式不是默認方案啊,不一發(fā)現(xiàn)啊。

  1. 錯誤處理問題
    AsyncTask沒有對發(fā)生的一些異常進行處理,你只能在onBackground里進行一些判斷,但之外的一些異常情況發(fā)生你都無法了解,比如線程異常退出等。

  2. 多個任務的管理問題
    如果需要多個后臺任務,需要新建多個AsyncTask來執(zhí)行任務,在需要退出的時候你需要對每一個都進行一定的處理來避免內存泄露以及UI問題,這是一個很麻煩的事情。

如果你使用AsyncTask默認的執(zhí)行方式,出了問題都很難排查。你可以保證你能正確使用AsyncTask,但你沒法保證別人也能正確使用啊,這就是別人給你挖的坑,但是你跳了進去啊,關鍵你可能都不知道到底哪個AsyncTask在執(zhí)行,可能引用就發(fā)生在第三方庫的也有可能啊。

替代方案

基于上述實際存在的問題尤其是并行串行問題,寫了一個類似AsyncTask的庫AsyncTaskScheduler,處理了上述的一些實際存在的問題。
細節(jié)介紹及使用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容