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:
- Making an AJAX call, and updating the UI once I receive a response - I use a simple
AsyncTask
for this. - Doing the above repeatedly, at regular intervals.
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.
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);
}
}
}
Thanks in advance
EDIT: 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
);
}
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?How can I "stop" the updates? One way I thought of was to make the very first
AsyncTask
instance as a member variable of theActivity
. That way, I can invokecancel(true)
on it and hope that this will "stop" the tasks.
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).
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()
).
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.
cancel(true)
inonPause
andonDestroy()
did not do the trick - it never callsonCancelled()
which I overrode in my AsyncTask. I cannot think of a way to use theisCancelled()
method to influence the behavior inside ofdoInBackground()
. I guess I'll have to go the AlarmManager way. I'll give it a try. – Simplehearted