Android:使用 AsyncTask 进行重复 Ajax 调用的含义 [英] Android: Implication of using AsyncTask to make repeated Ajax Calls
问题描述
我需要我的 Android 应用程序使用 AJAX 调用定期从服务器获取数据,并相应地更新 UI(只是一堆需要使用 setText() 更新的
TextView
).请注意,这涉及 2 个任务:
I need my Android app to periodically fetch data from a server using AJAX calls, and update the UI accordingly (just a bunch of TextView
s that need to be updated with setText()
). Note that this involves 2 tasks:
- 进行 AJAX 调用,并在收到响应后更新 UI - 为此,我使用了一个简单的
AsyncTask
. - 定期重复上述操作.
我还没有想出一种优雅的方法来实现上面的第 2 点.目前,我只是从 OnPostExecute()
执行任务本身.我在 SO 上的这个线程 上读到,我不需要担心垃圾收集与 AsyncTask 对象有关.
I haven't figured out an elegant way to achieve Point 2 above. Currently, I am simply executing the task itself from OnPostExecute()
. I read on this thread at SO that I need not worry about garbage collection as far as the AsyncTask objects are concerned.
但我仍然不确定如何设置一个计时器,以便在它到期后触发我的 AsyncTask.任何指针将不胜感激.这是我的代码:
But I'm still unsure as to how I set up a timer that will fire my AsyncTask after it expires. Any pointers will be appreciated. Here is my code:
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 小时内回复的声誉.
I tried posting an answer but couldn't do it since I don't have the reputation to answer within 8 hours.
好吧,所以我找到了解决方案.不过我不相信.
Well, so I found a solution. I'm not convinced however.
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.另外,我想知道
AsyncTask
如何成为 GC 的候选对象,除非onPostExecute()
完成?
Are there any flip sides that I should be aware of when I use this? In particular, I am seeing lots of GCs happening in the LogCat. Also, I am wondering how an
AsyncTask
can be candidate for GC unless theonPostExecute()
completes?
如何停止"更新?我想到的一种方法是将第一个 AsyncTask
实例作为 Activity
的成员变量.这样,我可以在它上面调用 cancel(true)
并希望这会停止"任务.
How can I "stop" the updates? One way I thought of was to make the very first AsyncTask
instance as a member variable of the Activity
. That way, I can invoke cancel(true)
on it and hope that this will "stop" the tasks.
<小时>
解决方案:
如果有人正在寻找类似的东西 - 我在这里提到的所有解决方案都不能令人满意.它们都遇到 OutOfMemory
问题.我没有调试 OOM 的细节,但我怀疑这可能是因为递归,或者因为将 HTTP 相关的对象作为 AsyncTask
中的成员变量而不是作为成员变量Activity
(主要是因为没有重用 HTTP 和其他对象).
SOLUTION:
In case anyone is looking for something similar - none of the solutions I mentioned here work satisfactorily. They all suffer from OutOfMemory
issues. I did not debug into the details of the OOM, but I suspect it could either be because of the recursion, or because of having HTTP-related objects as member variables in the AsyncTask
rather than as members of the Activity
(basically because of NOT reusing HTTP and other objects).
我为另一种方法放弃了这种方法 - 在我的 AsyncTask
的 doInBackground()
中无休止地进行 Ajax 调用;并在 onProgressUpdate()
中更新 UI.这样我也避免了维护太多线程或 Handler
来更新 UI 的开销(记住 UI 可以在 onProgressUpdate()
中更新).
I discarded this approach for a different one - making my Ajax Calls endlessly in the doInBackground()
of my AsyncTask
; and updating the UI in onProgressUpdate()
. That way I also avoid the overhead of maintaining too many threads or Handler
s for updating the UI (remember UI can be updated in onProgressUpdate()
).
这种方法还消除了对 Timer
s 和 TimerTask
s 的需要,有利于使用 Thread.sleep()
代替.SO 上的这个线程 有更多细节和代码片段也是.
This approach also eliminates the need for Timer
s and TimerTask
s, favoring the use of Thread.sleep()
instead. This thread on SO has more details and a code snippet too.
推荐答案
在任何 View
上调用 postDelayed()
来安排一大块代码在主视图上运行一定延迟后的应用程序线程.在 AsyncTask
的 onPostExecute()
中执行此操作以创建并执行另一个 AsyncTask
.
Call postDelayed()
on any View
to schedule a hunk of code to be run on the main application thread after a certain delay. Do this in onPostExecute()
of the AsyncTask
to create and execute another AsyncTask
.
您可以使用 AlarmManager
,正如其他人所引用的那样,但我同意您的看法,对于纯粹在活动中发生的计时来说,这感觉有点矫枉过正.
You could use AlarmManager
, as others have cited, but I would agree with you that it feels a bit like overkill for timing that occurs purely within an activity.
话虽如此,如果无论活动是否存在都应该发生 AJAX 调用,请务必考虑切换到 AlarmManager
和 IntentService
.
That being said, if the AJAX calls should be occurring regardless of whether the activity exists, definitely consider switching to AlarmManager
and an IntentService
.
这篇关于Android:使用 AsyncTask 进行重复 Ajax 调用的含义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!