Anko的uiThread偶尔不会被解雇

时间:2017-10-17 17:23:48

标签: android asynchronous kotlin anko

我目前正在使用Anko的 doAsync 来处理异步任务。 具体来说,我使用它将响应 json 解析为数据对象的 ArrayList ,如下所示:

// Asynchronously parse server response
doAsync {
    val itemlist = parseResponse(response)
    uiThread {
        Otto.INSTANCE.post(UpdateRedeemedVoucherViewsEvent(itemlist))
    }
}

大多数情况下,就像 Google Pixel(Android 8.0.0)一样,这很好用。我的对象被解析, Otto总线事件将被放在 ui线程上。

但在极少数情况下,此过程失败。 到目前为止,我注意到ui线程调用不会在 Galaxy S5 Mini(Android 5.1.1)上触发。尽管我的数据在没有任何错误或异常的情况下进行了解析,但 uiThread 括号中的代码段不会被执行。

到目前为止,我无法确定此行为的任何原因。没有logcat日志,没有。没有出现此错误的方案。

是否有人与kotlin和/或Anko有相同或类似的问题?

更新:我自己找到了解决方案,请参阅下面的答案以获得解释。

2 个答案:

答案 0 :(得分:1)

我有同样的问题,这是因为在后台发生了未捕获的异常。

使用try / catch包围您的后台任务,您应该能够看到正在发生的事情。

doAsync {
    try {
        val itemlist = parseResponse(response)
    } catch(t: Throwable) {
        //TODO log your exception
    ]
    uiThread {
        Otto.INSTANCE.post(UpdateRedeemedVoucherViewsEvent(itemlist))
    }
}

答案 1 :(得分:1)

谢谢你的帮助。 我自己想出来了,所以我发布这个答案,以防其他人遇到这个问题。

TL; DR:上下文丢失,因此 uiThread 将不会被执行

解决方案: 我偶然发现了post,其中提到了 uiThread 方法的一个重要特性:

  

基本上你有一个异步函数,可以在另一个线程中执行它的代码,并且可以使用uiThread返回主线程。 async是为Context实现的扩展函数,它将使用它的弱引用,因此它不会阻止GC释放其内存。

经过进一步调查,我在解析完成后找到了以下日志,并且应该调用 uiThread

I/art: Background partial concurrent mark sweep GC freed 30879(16MB) AllocSpace objects, 16(2MB) LOS objects, 40% free, 16MB/27MB, paused 2.123ms total 196.372ms

所以似乎确实存在一些GC动作,可能会或者可能不会释放上下文

为了防止这种情况,我使用的是Ankos runOnUiThread ,在给定的上下文引用中可以调用

// Asynchronously parse server response
doAsync {
    val itemlist = parseResponse(response)
    context.runOnUiThread {
        Otto.INSTANCE.post(UpdateRedeemedVoucherViewsEvent(itemlist))
    }
}

据我所知,这似乎已经成功了。