我已经调查了这个问题几个月了,提出了不同的解决方案,我不满意,因为它们都是巨大的黑客。我仍然无法相信一个在设计上有缺陷的类被纳入框架,而没有人谈论它,所以我想我一定是错过了什么。
问题出在AsyncTask上。根据文档它
允许执行后台 操作并在 UI线程,而不需要操作 线程和/或处理程序。
然后,该示例继续展示如何在onPostExecute()中调用一些示例性的showDialog()方法。然而,这对我来说似乎完全是人为的,因为显示一个对话框总是需要一个对有效上下文的引用,而AsyncTask决不能拥有对上下文对象的强引用。
原因很明显:如果触发任务的活动被破坏了怎么办?这种情况经常发生,比如你翻动了屏幕。如果任务保存了对创建它的上下文的引用,那么您不仅保留了一个无用的上下文对象(窗口将被销毁,任何UI交互都将失败并出现异常!),甚至还可能产生内存泄漏。
除非我的逻辑在这里有缺陷,否则这转化为:onPostExecute()是完全无用的,因为如果你不能访问任何上下文,这个方法在UI线程上运行有什么好处?你不能在这里做任何有意义的事情。
One workaround would be to not pass context instances to an AsyncTask, but a Handler instance. That works: since a Handler loosely binds the context and the task, you can exchange messages between them without risking a leak (right?). But that would mean that the premise of AsyncTask, namely that you don't need to bother with handlers, is wrong. It also seems like abusing Handler, since you are sending and receiving messages on the same thread (you create it on the UI thread and send through it in onPostExecute() which is also executed on the UI thread).
最重要的是,即使使用了这种变通方法,您仍然会遇到这样的问题:当上下文被破坏时,您没有它所触发的任务的记录。这意味着在重新创建上下文时,你必须重新启动任何任务,例如在屏幕方向改变之后。这既缓慢又浪费。
My solution to this (as implemented in the Droid-Fu library) is to maintain a mapping of WeakReferences from component names to their current instances on the unique application object. Whenever an AsyncTask is started, it records the calling context in that map, and on every callback, it will fetch the current context instance from that mapping. This ensures that you will never reference a stale context instance and you always have access to a valid context in the callbacks so you can do meaningful UI work there. It also doesn't leak, because the references are weak and are cleared when no instance of a given component exists anymore.
不过,这是一种复杂的解决方法,需要子类化一些Droid-Fu库类,这是一种相当具有侵入性的方法。
现在我只是想知道:我只是大量的遗漏了一些东西或AsyncTask真的完全有缺陷?你的工作经历如何?你是如何解决这些问题的?
谢谢你的建议。