如何在屏幕旋转期间处理AsyncTask?

Jan*_*usz 86 android screen-rotation android-asynctask

我读了很多关于如何保存我的实例状态或如何在屏幕旋转期间处理我的活动被破坏的内容.

似乎有很多可能性,但我还没有想出哪一个最适合检索AsyncTask的结果.

我有一些AsyncTasks只是再次启动并调用isFinishing()活动的方法,如果活动正在完成,他们不会更新任何东西.

问题是我有一个任务对Web服务发出请求失败或成功的任务,并且重新启动任务会导致用户的经济损失.

你怎么解决这个问题?可能的解决方案有哪些优点或缺点?

Rom*_*Guy 46

您可以AsyncTaskcode.google.com/p/shelves查看我如何处理和方向更改.有多种方法可以做到这一点,我在这个应用程序中选择的方法是取消当前正在运行的任务,保存其状态并在Activity创建新状态时启动具有已保存状态的新状态.它很容易做到,效果很好,作为奖励,它会在用户离开应用程序时停止执行任务.

你也可以onRetainNonConfigurationInstance()用来传递你AsyncTask的新东西Activity(注意不要以前Activity这种方式泄漏.)

  • AsyncTask来自UserTask.我最初为自己的应用程序编写了UserTask,后来将其转换为AsyncTask.很抱歉,我忘记了它已重命名. (7认同)

Vit*_*nko 10

这是我见过的关于Android的最有趣的问题!!! 实际上我在过去几个月里一直在寻找解决方案.还是没有解决.

小心,简单地覆盖

android:configChanges="keyboardHidden|orientation"
Run Code Online (Sandbox Code Playgroud)

东西还不够.

考虑用户在AsyncTask运行时接到电话的情况.您的请求已由服务器处理,因此AsyncTask正在等待响应.在这一刻你的应用程序进入后台,因为手机应用程序刚刚进入前台.操作系统可能会杀死您的活动,因为它在后台.


Jim*_*ler 6

我的第一个建议是确保您确实需要在屏幕旋转时重置您的活动(默认行为).每次我遇到旋转问题时我都会<activity>在AndroidManifest.xml中将此属性添加到我的标签中,并且很好.

android:configChanges="keyboardHidden|orientation"
Run Code Online (Sandbox Code Playgroud)

它看起来很奇怪,但是onConfigurationChanged()如果你不提供它,它会把它交给你的方法,除了重新测量布局之外别无其他任何事情,这似乎是在大多数时候处理旋转的完美的方法.

  • 使用此技术可以防止您轻松使用配置特定的资源.例如,如果您希望您的布局或绘图或字符串或其他在纵向和横向上有所不同,您将需要默认行为.覆盖配置更改应该只在非常特殊的情况下(游戏,网络浏览器等)完成,而不是出于懒惰或方便,因为你在限制自己. (75认同)
  • 那就是它,罗曼."如果你想要你的布局或绘图或字符串或任何在纵向和横向上不同的东西,你将需要默认行为",我相信这是一个比你想象的更罕见的用例.我认为大多数开发人员都称之为"非常具体的案例".使用适用于所有维度的相对布局是最佳实践,并不是那么难.谈论懒惰是非常误导的,这些技术是为了改善用户体验而不是缩短开发时间. (37认同)
  • 我同意罗曼(他知道他在说什么,他开发了操作系统).当您想要将应用程序移植到平板电脑并且拉伸时UI看起来很糟糕时会发生什么?如果你采用这个答案的方法,你将需要重新编写你的整个解决方案,因为你使用这个懒惰的黑客. (9认同)
  • 但这会阻止Activity更改布局.因此迫使用户按照您的应用程序而不是他的需要指定的特定方向使用他的设备. (5认同)
  • 我发现这适用于LinearLayout,但是当使用RelativeLayout时,它不会在切换到横向模式时正确地重新绘制布局(至少不在N1上).请看这个问题:http://stackoverflow.com/questions/2987049/how-to-refresh-an-android-relativelayout-when-orientation-changes-without-restart (2认同)

net*_*ein 6

为什么不总是在Android提供的Singleton上保留对当前AsyncTask的引用?

每当任务开始时,在PreExecute或构建器上,您都定义:

((Application) getApplication()).setCurrentTask(asyncTask);

只要它完成,您将其设置为null.

这样你总有一个参考,允许你做一些像onCreate或onResume这样的东西,用于你的特定逻辑:

this.asyncTaskReference = ((Application) getApplication()).getCurrentTask();

如果它为null,你知道目前没有运行!

:-)

  • 我想:如果应用程序被杀死,整个应用程序都被杀死(因此,所有AsyncTasks也被杀死)? (7认同)
  • `Application`实例有自己的生命周期 - 它也可以被OS杀死,所以这个解决方案可能会导致难以重现的bug. (6认同)

use*_*491 5

最正确的方法是使用片段来保留异步任务的实例,通过旋转。

这是一个非常简单示例的链接,可以轻松地将这种技术集成到您的应用程序中。

https://gist.github.com/daichan4649/2480065