Android屏幕旋转触发多个异步任务线程

Android屏幕旋转触发多个异步任务线程,android,android-listview,android-asynctask,Android,Android Listview,Android Asynctask,在活动中,我创建了一个处理程序,每45秒启动一次AsyncTask,以刷新ListView的DataAdapter的内容。AsyncTask工作得很好,通过ProgressUpdate和Toast消息让用户了解进度 由于线程的doInBackground是fire-and-forget,不可重用,因此我必须从我的Hander创建一个新的异步任务实例,该实例每45秒启动一次。问题是,当屏幕旋转时,我会收到并发消息,因为Hander被重新创建并创建了AsyncTask的一个新实例,因此友好的用户通过

在活动中,我创建了一个处理程序,每45秒启动一次AsyncTask,以刷新ListView的DataAdapter的内容。AsyncTask工作得很好,通过ProgressUpdate和Toast消息让用户了解进度

由于线程的doInBackground是fire-and-forget,不可重用,因此我必须从我的Hander创建一个新的异步任务实例,该实例每45秒启动一次。问题是,当屏幕旋转时,我会收到并发消息,因为Hander被重新创建并创建了AsyncTask的一个新实例,因此友好的用户通过ProgressUpdates和Toast消息进行处理的过程非常复杂,这使得使用ListView非常困难

请不要建议将此作为解决方案:android:screenOrientation=“肖像”不是一个选项

对于一些必须频繁运行的任务,我应该只使用自定义线程而不是AsyncTask类吗?ToDo:未显示,我必须稍后从传感器的onSensorChanged事件更新适配器,以更新ListView中每个位置的方向角,我将在单独的AsyncTask类上运行它,因为我不需要在每次设备方向角发生更改时通知用户

由于AsyncThread不能被重用,我这样做完全错了吗?简而言之,让活动刷新ListView并在执行此操作时避开UI线程的最佳方法是什么

问题是,当屏幕旋转时,由于Hander被重新创建并创建了AsyncTask的一个新实例,因此我收到的并发消息会消失

引用API的原因:

除非您另有指定,否则配置更改(如屏幕方向、语言、输入设备等的更改)将导致当前活动被销毁,并根据需要执行onPause()、onStop()和onDestroy()的正常活动生命周期过程

因此,每个对象都有一个活动范围生命周期(即在活动类中定义的处理程序、异步任务等)会受到此活动的影响。但是,您可以绕过此活动,如“活动-配置更改”部分后面的段落所述:

在某些特殊情况下,您可能希望基于一种或多种类型的配置更改绕过活动的重新启动。这是通过清单中的android:configChanges属性完成的。对于您所说要在此处处理的任何类型的配置更改,您将收到对当前活动的onConfigurationChanged(配置)方法的调用,而不是重新启动。但是,如果配置更改涉及任何您不处理的内容,则活动仍将重新启动,并且不会调用onConfigurationChanged(配置)

与主题无关,但作为一种良好的实践,当活动即将完成时(即在onDestroy()方法中),您应该始终正确地销毁使用过的对象(处理程序、AsyncTask等)

对于一些必须频繁运行的任务,我应该只使用自定义线程而不是AsyncTask类吗


AsyncTask非常方便,但不适合周期性任务,我会使用ScheduledExecutorService或TimerTask。在这种情况下,请查看示例代码。

能否发布一些代码?了解你的问题所在可能会很有用

正如约克所指出的,您可能应该使用
TimerTask
。似乎它更适合你正在尝试做的事情

如果是处理程序的新实例创建了问题,您可以尝试以下方法:

private Handler mHandler = null;

@Override
public void onCreate(Bundle _savedInstanceState) {
    super.onCreate(_savedInstanceState);
    setContentView(R.layout.my_layout);

    if (mHandler == null) {
        // TODO create your handler here
    }
}
编辑: 您也可以测试_savedInstanceState==null。
_savedInstanceState用于保存活动的状态,因此转动手机不再是问题。
但是,如果您离开该活动,然后返回该活动,它将创建一个新的处理程序(除非您将其实例化为静态变量)

你能给我们展示一下你活动的onCreate()和onStart()方法吗?是的,我同意York的观点,我打算用计时器来代替。顺便说一句,我确实尝试了你的建议,在创建新的处理程序实例之前检查mHandler是否为null,该实例将创建新的Runnable实例。。。但我仍然存在旋转多个AsynTask线程的问题,我可以通过来回翻转手机来轻松地使应用程序崩溃:致命异常:com.echo5.appname.ActivityStationList.onTaskComplete上的主java.lang.NullPointerException(ActivityStationList.java:152)位于com.echo5.appname.threads.AsyncTaskManager.onComplete(AsyncTaskManager.java:61)在com.echo5.appname.ActivityStationList$UpdateStationTask.onPostExecute(ActivityStationList.java:573)在com.echo5.appname.ActivityStationList$UpdateStationTask.onPostExecute(ActivityStationList.java:1)在android.os.AsyncTask.finish(AsyncTask.java:417)在android.os.AsyncTask.access$300(AsyncTask.java:127)android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)android.os.Handler.dispatchMessage(Handler.java:99)android.os.Looper.loop(Looper.java:130)android.app.ActivityThread.main(ActivityThread.java:3687)java.lang.reflect.Method.Invokenactive(本机方法)java:507)位于com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)处,位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)处,位于dalvik.system.NativeStart.main(本机方法)我编辑了我的帖子。如果您尝试对_savedInstanceState和作为静态变量的处理程序进行测试,请让我知道它是否对您有效。感谢York,在进一步阅读之后,我没有使用最佳线程模型来完成此任务,并且发现计时器将更适合我尝试完成的任务。这是主要参考异步任务的ce:我还发现这在决定TimerTask还是Schedu时很有用