Muh*_*lib 55 java android weak-references android-asynctask
我对android中这种简单的常见情况有疑问.
我们有一个主要的活动,我们调用AsyncTask以及mainactivity的引用,以便AsyncTask可以更新MainActivity上的视图.
我将把事件分解为几步
上面的解决方案是按照"Pro Android 4"一书的建议在AsyncTask中保留WeakReference.
WeakReference<Activity> weakActivity;
in method onPostExecute
Activity activity = weakActivity.get();
if (activity != null) {
// do your stuff with activity here
}
Run Code Online (Sandbox Code Playgroud)
这是如何解决这种情况的?
我的问题是,如果我的asynctask正在下载10个文件,并且在完成5后重新启动活动(因为方向改变),那么我的FileDownloadingTask会再次被调用吗?
最初调用的先前AsyncTask会发生什么?
谢谢,我为问题的长度道歉.
Ste*_*vie 34
这是如何解决这种情况的?
在WeakReference允许Activity进行垃圾回收,所以你不要有内存泄漏.
空引用意味着AsyncTask 不能盲目地尝试更新不再附加的用户界面,这会抛出异常(例如视图未附加到窗口管理器).当然,您必须检查null以避免NPE.
如果我的asynctask正在下载10个文件,并且在完成5后重新启动活动(因为方向改变),那么我的FileDownloadingTask会再次被调用吗?
取决于你的实现,但可能是 - 如果你不刻意做一些事情来重复下载不必要,比如在某处缓存结果.
AsyncTask最初调用的前一个会发生什么?
在Android的早期版本中,它将运行完成,仅下载所有文件以将它们丢弃(或者根据您的实现缓存它们).
在较新的Android中,我怀疑是否AsyncTask会被Activity启动它们而被杀死,但我怀疑的基础只是RoboSpice的内存泄漏演示(见下文)实际上并没有在我的JellyBean设备上泄漏.
如果我可以提供一些建议:AsyncTask不适合执行可能长时间运行的任务,例如网络.
IntentService如果您可以接受单个工作线程,那么这是一种更好(并且仍然相对简单)的方法.Service如果你想控制线程池,请使用(本地)- 并注意不要在主线程上工作!
如果你正在寻找一种在后台可靠地执行网络的方法,RoboSpice似乎很好(免责声明:我没有尝试过;我没有附属).游戏商店中有一个RoboSpice Motivations演示应用程序,通过演示可能出错的所有内容(包括WeakReference解决方法)来解释为什么要使用它AsyncTask.
另请参见此主题:AsyncTask在概念上是否真的存在缺陷,或者我只是遗漏了什么?
更新:
我创建了一个github项目,下载使用IntentService另一个SO问题的例子(如何修复android.os.NetworkOnMainThreadException?),但我认为这也与此相关.它具有额外的优势,通过返回结果onActivityResult,当您旋转设备时正在进行的下载将传递给重新启动的Activity.
该WeakReference级基本上只是防止JRE增加对给定实例的引用计数器.
我不会直接进入Java的内存管理并直接回答您的问题:WeakReference通过提供AsyncTask一种了解其父活动是否仍然有效的方法来解决问题.
方向更改本身不会自动重启AsyncTask.您必须使用已知机制(onCreate/ onDestroy,onSave/RestoreInstanceState)编写所需行为.
关于原版AsyncTask,我不是100%确定会发生以下哪种选择:
AsyncTask,因为唯一对象持有它(原始Activity)被销毁AsyncTask对象的引用,阻止其垃圾收集,从而有效地AsyncTask在后台完成无论哪种方式,最好AsyncTask手动中止/暂停和重启/恢复(或将其交给新的Activity),或者使用Service替代.
| 归档时间: |
|
| 查看次数: |
16927 次 |
| 最近记录: |