0

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

由于线程的 doInBackground 是触发后忘记且不可重复使用,因此我必须从我的 Hander 创建一个 AsyncTask 的新实例,该实例每 45 秒触发一次。问题是当屏幕旋转时,我收到并发消息,因为重新创建了 Hander 并创建了 AsyncTask 的新实例,因此通过 ProgressUpdates 和 Toast 消息的友好用户进度是压倒性的,使得使用 ListView 变得困难。

请不要将此作为解决方案: android:screenOrientation="portrait" 不是一个选项。

对于必须如此频繁运行的东西,我应该只使用自定义线程而不是 AsyncTask 类吗?ToDo:未显示,我必须稍后从传感器的 onSensorChanged 事件更新适配器以更新 ListView 中每个位置的方位,我打算在单独的 AsyncTask 类上运行它,因为我不需要每次都通知用户设备轴承发生了变化。

由于 AsyncThread 不能被重用,我做错了吗?简而言之,让 Activity 刷新 ListView 并在这样做时远离 UI 线程的最佳方法是什么?

4

2 回答 2

1

问题是当屏幕旋转时,我收到并发消息,因为重新创建了 Hander 并创建了 AsyncTask 的新实例。

来自 API活动 - 配置更改的原因引用:

除非您另外指定,否则配置更改(例如屏幕方向、语言、输入设备等的更改)将导致您当前的活动被破坏,并通过 onPause()、onStop() 和onDestroy() 视情况而定。

因此,每个对象都有一个活动范围的生命周期(即在您的活动类中定义的 Handler、AsyncTask 等),都会受到此活动重新创建的影响。但是,您可以绕过此活动重新创建,如后面的“活动 - 配置更改”部分所述:

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

与主题无关,但作为一个好习惯,当活动即将结束时(即在 onDestroy() 方法中),您应该始终正确地销毁使用的对象(Handler、AsyncTask 等)。

对于必须如此频繁运行的东西,我应该只使用自定义线程而不是 AsyncTask 类吗?

AsyncTask 非常方便,但不适合定期任务,在这种情况下我会使用 ScheduledExecutorService 或 TimerTask,请在此处查看我的答案以获取示例代码。

于 2012-05-05T09:54:26.753 回答
0

你能发布一些你的代码吗?了解您的问题出在哪里可能会很有用。

正如york指出的那样,您可能应该使用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 用于保存活动的状态,因此转动手机不再是问题。但是,如果您离开活动然后返回到它,它将创建一个新的处理程序(除非您将其实例化为静态变量)。

于 2012-05-05T19:37:50.497 回答