Raj*_*aja 72 android android-asynctask
我有一个AsyncTask对象,它在创建活动时开始执行,并在后台执行操作(下载最多100个图像).一切都很好,但有一种我不能理解的特殊行为.
例如:当Android屏幕的方向发生变化时,活动将被销毁并再次创建.所以我重写onRetainNonConfigurationInstance()方法并保存在AsyncTask中执行的所有下载数据.我这样做的目的是每次在方向更改期间销毁活动时都不会运行AsyncTask,但正如我在日志中可以看到的,之前的AsyncTask仍然在执行.(虽然数据保存正确)
我甚至尝试在活动的onDestroy()方法中取消AsyncTask,但日志仍然显示AsyncTask正在运行.
这是非常奇怪的行为,如果有人能告诉我停止/取消AsyncTask的正确程序,真的很感激.
谢谢
Sni*_*las 144
@Romain Guy给出的答案是正确的.不过,我想添加一个信息补充,并给出一个指向库或2的指针,可以用于长时间运行的AsyncTask,甚至可以用于面向网络的asynctasks.
AsyncTasks专为在后台执行操作而设计.是的,您可以使用该cancel方法停止它.当您从Internet下载内容时,我强烈建议您在IO阻塞状态下处理您的线程.您应按照以下方式组织下载:
public void download() {
//get the InputStream from HttpUrlConnection or any other
//network related stuff
while( inputStream.read(buffer) != -1 && !Thread.interrupted() ) {
//copy data to your destination, a file for instance
}
//close the stream and other resources
}
Run Code Online (Sandbox Code Playgroud)
使用该Thread.interrupted标志将帮助您的线程正确地退出阻塞io状态.您的线程将更灵敏地调用该cancel方法.
但如果您的AsyncTask持续时间过长,那么您将面临两个不同的问题:
我想介绍的库RoboSpice使用后台服务来执行这种请求.它专为网络请求而设计.它提供了其他功能,例如自动缓存请求的结果.
这就是为什么AsyncTasks对于长时间运行的任务不利的原因.以下推理是对RoboSpice动机的改编:适用于解释为什么使用RoboSpice满足Android平台需求的应用程序.
AsyncTasks不遵循Activity实例的生命周期.如果在Activity中启动AsyncTask并旋转设备,则将销毁Activity并创建新实例.但AsyncTask不会死.它会继续生存直到它完成.
完成后,AsyncTask将不会更新新Activity的UI.实际上,它更新了之前不再显示的活动实例.这可能导致java.lang.IllegalArgumentException类型的异常:如果您使用findViewById来检索Activity内的视图,则View不会附加到窗口管理器.
将AsyncTasks创建为活动的内部类非常方便.由于AsyncTask需要在任务完成或正在进行时操纵Activity的视图,使用Activity的内部类似乎很方便:内部类可以直接访问外部类的任何字段.
然而,这意味着内部类将在其外部类实例上保存一个不可见的引用:Activity.
从长远来看,这会产生内存泄漏:如果AsyncTask持续很长时间,它会使活动保持"活着",而Android则希望摆脱它,因为它无法再显示.该活动不能被垃圾收集,这是Android在设备上保留资源的核心机制.
您可以使用一些变通方法来创建长时间运行的异步任务,并根据活动的生命周期管理其生命周期.您可以在活动的onStop方法中取消AsyncTask,也可以让异步任务完成,而不是松开其进度并将其重新链接到下一个活动实例.
这是可能的,我们展示了RobopSpice的动机,但它变得复杂,而且代码并不是真正的通用.此外,如果用户离开活动并返回,您仍将失去任务的进度.Loaders也出现了同样的问题,尽管它与上面提到的重新链接解决方法的AsyncTask相比更简单.
最好的选择是使用服务来执行长时间运行的后台任务.这正是RoboSpice提出的解决方案.同样,它专为网络设计,但可以扩展到非网络相关的东西.该库具有大量功能.
你可以通过信息图表在不到30秒的时间内了解它.
对于长时间运行的操作使用AsyncTasks确实是一个非常糟糕的主意.然而,它们适用于短期生活,例如在1或2秒后更新视图.
我鼓励您下载RoboSpice Motivations应用程序,它真正深入地解释了这一点,并提供了有关网络相关内容的不同方法的示例和演示.
如果您正在为非网络相关任务(例如没有缓存)寻找RoboSpice的替代方案,您还可以查看Tape.
Cag*_*lan 15
罗曼盖伊是对的.实际上,异步任务负责在任何情况下完成自己的工作.中断不是最好的方法,所以你应该不断检查是否有人要你取消或停止你的任务.
假设你AsyncTask在循环中做了很多次.然后你应该检查isCancelled()每个循环.
while ( true ) {
if ( isCancelled())
break;
doTheTask();
}
Run Code Online (Sandbox Code Playgroud)
doTheTask() 是你真正的工作,在每个循环中你做之前,你检查你的任务是否应该被取消.
一般来说,你应该在你的AsyncTask班级设置一个旗帜,或者从你那里返回一个合适的结果,doInBackground()这样onPostExecute()你就可以检查你是否可以完成你想要的任务,或者你的工作是否在中间被取消.
| 归档时间: |
|
| 查看次数: |
65896 次 |
| 最近记录: |