【发布时间】:2011-07-13 11:48:59
【问题描述】:
我需要我的 Android 应用定期使用 AJAX 调用从服务器获取数据,并相应地更新 UI(只是一堆需要使用 setText() 更新的 TextViews)。请注意,这涉及 2 个任务:
- 进行 AJAX 调用,并在收到响应后更新 UI - 为此我使用了一个简单的
AsyncTask。 - 定期重复上述操作。
我还没有找到实现上述第 2 点的优雅方法。目前,我只是从OnPostExecute() 执行任务本身。我在this thread at SO 上读到,就 AsyncTask 对象而言,我不必担心垃圾收集。
但我仍然不确定如何设置一个计时器,该计时器将在我的 AsyncTask 到期后触发它。任何指针将不胜感激。这是我的代码:
public class MyActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new AjaxRequestTask().execute(MY_REST_API_URL);
}
private void updateReadings(String newReadings) {
//Update the UI
}
class AjaxRequestTask extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... restApiUrl) {
//Do AJAX Request
}
@Override
protected void onPostExecute(String result) {
updateReadings(result);
/*Is there a more elegant way to achieve this than create a new AsyncTask object every 10 seconds? Also, How can I update the UI if I create a timer here? */
new AjaxRequestTask().execute(MY_REST_API_URL);
}
}
}
提前致谢
编辑: 我尝试发布答案,但无法发布,因为我没有在 8 小时内回答的声誉。
好吧,所以我找到了解决方案。不过我不相信。
protected void onPostExecute(String result) {
updateReadings(result);
// super.onPostExecute(result);
new Timer().schedule(
new TimerTask() {
@Override
public void run() {
new AjaxRequestTask().execute(MY_REST_API_URL);
}
},
TIMER_ONE_TIME_EXECUTION_DELAY
);
}
当我使用它时,是否有任何反面需要注意?特别是,我看到 LogCat 中发生了很多 GC。另外,我想知道除非
onPostExecute()完成,否则AsyncTask如何成为GC 的候选人?如何“停止”更新?我想到的一种方法是将第一个
AsyncTask实例作为Activity的成员变量。这样,我可以在其上调用cancel(true)并希望这将“停止”任务。
解决方案:
如果有人正在寻找类似的东西 - 我在这里提到的解决方案都不能令人满意。他们都遭受OutOfMemory 问题的困扰。我没有调试 OOM 的细节,但我怀疑这可能是因为递归,或者因为 HTTP 相关对象作为 AsyncTask 中的成员变量而不是 Activity 的成员(基本上因为没有重用 HTTP 和其他对象)。
我放弃了这种方法,换了一种方法——在我的AsyncTask 的doInBackground() 中无休止地进行Ajax 调用;并更新onProgressUpdate() 中的用户界面。这样我也避免了维护太多线程或Handlers 来更新 UI 的开销(记住 UI 可以在 onProgressUpdate() 中更新)。
这种方法还消除了对Timers 和TimerTasks 的需要,而倾向于使用Thread.sleep()。 This thread on SO 有更多细节和代码 sn-p。
【问题讨论】:
-
我在上面的编辑中提到的“解决方案”有严重的缺陷——正如怀疑的那样,它会导致“无限循环”。在
onPause和onDestroy()中调用cancel(true)并没有成功——它从不调用我在AsyncTask 中覆盖的onCancelled()。我想不出一种方法来使用isCancelled()方法来影响doInBackground()内部的行为。我想我将不得不采用 AlarmManager 的方式。我试试看。
标签: android android-asynctask timertask