详细解读AsyncTask的黑暗面以及一种替代方案

基于最新版本的AsyncTask详细解读主要是一些AsyncTask的原理解读,本篇将分析AsyncTask使用的受限部,这里可能会有一些你以前没注意到的点,同时提供一个替代方案AsyncTaskScheduler

一些关于AsyncTask的指责

如果搜索关键词"AsyncTask的缺陷",会有很多关于AsyncTask缺陷的文章,很多是基于以下几个问题,但这些问题真的是AsyncTask自身的问题还是使用不当导致的呢?这真的需要好好分析一下,不能人云亦云,强行甩锅。

  1. 生命周期和内存泄漏
    "当Activity结束或者退出应用时AsyncTask会一直执行doInBackground()方法直到方法执行结束,这可能会导致在onPostExecute时view不存在而导致崩溃溃,以及可能的内存泄露"。
    如果退出Activity时AsyncTask扔在执行,上面说的的却会发生,但这些问题需要由使用者来解决而不是AsyncTask来解决,因为AsyncTask只是执行后台任务,它怎么知道你什么时候要终止,要退出,确定使用Handler时不会出现这样问题???


    怪我喽???

    所以应该在相应的生命周期如onDestory调用cancel取消任务,上面的问题就不会发生了,所有这个锅不应该AsyncTask来背。

  2. cancel不能正常取消的问题
    首先调用cancel终止AsyncTask的原理是对执行异步任务的线程调用interrupt()函数。
    首先,每个线程内部都有一个boolean型变量表示线程的中断状态,true代表线程处于中断状态,false表示未处于中断状态。
    而interrupt()方法的作用只是用来改变线程的中断状态(把线程的中断状态改为true,即被中断)。因此interrupt()方法代表着外界希望中断此线程,只是希望,具体怎么处理还是线程内部来做,一般情况下interrupt()方法可以使处于阻塞状态的线程抛出InterruptedException从而结束阻塞状态或则判断Thread.interrupted()来处理逻辑。所以如果你的AsyncTask后台任务有未做中断的处理肯定会一直执行这个线程。所以这需要你自己在doInbackground里进行中断处理,即使你认为这是个缺陷也应该是Thread类的缺陷,因为要用到线程处理异步任务,AsyncTask无法选择其他方式,而且调用cancel后onPostExecute也不会在执行了,不会导致UI线程的问题,所以这个锅也不应该AsyncTask来背。

  3. Activity意外重启,状态消失问题
    比如当用户旋转屏幕的时候Activity就会重新启动,如果之前有AsyncTask正在异步加载处理数据,那么之前的数据就会消失,而新的AsyncTask重新创建,这的却是个问题,但你用其他的方式进行请求同样会发生这个问题啊。

其实可能是我们的要求太多了,AsyncTask只是一个处理异步任务的工具,很多逻辑上的东西需要我们自己来处理,就像使用Handler和Thread,不正确处理同样会出现上述问题,这些总得来说就是异步带来的问题,这是一个时间和性能的选择问题,AsyncTask就是简化了包装了Handler的处理步骤而已。上面的这些更应该是一些重要的注意事项,而不是AsyncTask的问题

实际存在的问题

  1. 并行串行问题
    上面的一些可能是由于使用不当导致的,但并行串行问题方面AsyncTask问题很大。
    使用建议

    看AsyncTask源码文档时看到这样建议"AsyncTasks should ideally be used for short operations (a few seconds at the most",就是尽量执行一个短时间的任务,最对也就几秒的任务。当初还很疑惑,AsyncTask这玩意不就是用来处理后台任务的吗,又不是在主线程,为什么还限制短时间的任务,那要你何用啊。
    Excuse me ? ? ?

    基于最新版本的AsyncTask详细解读分析过在api11后AsyncTask默认的是串行执行任务,基本现上市面上的设备上都将是串行执行。自己可以写个Demo试试看。
    这些串行执行共用的AsyncTask的是一个线程池,这真的很严重。因为是顺序执行,导致你调用execute() 可能 没法立刻执行,也可能就执行不了,因为谁知道有没有其他的AsyncTask任务在执行啊,或者任务还是个很耗时的任务,或者就是个while(ture)循环或者for(;;)来一直处理一种后台任务,那么同一进程内的AsyncTask在这之后调用execute的都将无法执行。
    想当初初学Android时觉得AsyncTask真是个方便的东西,手机写了个基于socket通信的应用,doInbackground处理,然后直接通知UI。在doInbackground函数里处理一些连接以及数据流的接收及发送,socket的等待连接和数据结束都是阻塞的啊,现在回想起来当初真是年轻😃。

当然你可以立刻执行一个任务通过调用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)通过AsyncTask的THREAD_POOL_EXECUTOR线程池或者传入其他的线程池来立刻执行任务,但THREAD_POOL_EXECUTOR有最大并发数的限制,具体分析见基于最新版本的AsyncTask详细解读,但只执行一个任务时通过线程池来管理的也是无奈之举,而且这种方式不是默认方案啊,不一发现啊。

  1. 错误处理问题
    AsyncTask没有对发生的一些异常进行处理,你只能在onBackground里进行一些判断,但之外的一些异常情况发生你都无法了解,比如线程异常退出等。

  2. 多个任务的管理问题
    如果需要多个后台任务,需要新建多个AsyncTask来执行任务,在需要退出的时候你需要对每一个都进行一定的处理来避免内存泄露以及UI问题,这是一个很麻烦的事情。

如果你使用AsyncTask默认的执行方式,出了问题都很难排查。你可以保证你能正确使用AsyncTask,但你没法保证别人也能正确使用啊,这就是别人给你挖的坑,但是你跳了进去啊,关键你可能都不知道到底哪个AsyncTask在执行,可能引用就发生在第三方库的也有可能啊。

替代方案

基于上述实际存在的问题尤其是并行串行问题,写了一个类似AsyncTask的库AsyncTaskScheduler,处理了上述的一些实际存在的问题。
细节介绍及使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容