Мне нужно, чтобы мое приложение для Android периодически извлекало данные с сервера с помощью вызовов AJAX и соответственно обновляло пользовательский интерфейс (просто набор TextView
с, которые необходимо обновить с помощью setText()
).Обратите внимание, что это включает в себя 2 задачи:
- Выполнение вызова AJAX и обновление пользовательского интерфейса после получения ответа - для этого я использую простой
AsyncTask
. - Выполнение вышеуказанногонеоднократно, с регулярными интервалами.
Я не нашел элегантного способа достичь пункта 2 выше.В настоящее время я просто выполняю саму задачу из OnPostExecute()
.Я прочитал в этой теме на 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
);
}
Есть ли какие-то оборотные стороны, о которых я должен знать, когда я использую это?В частности, я вижу много GC, происходящих в LogCat.Кроме того, мне интересно, как AsyncTask
может быть кандидатом на сборщик мусора, если onPostExecute()
не завершится?
Как я могу "остановить" обновления?Один из способов, о котором я подумал, - создать самый первый экземпляр AsyncTask
в качестве переменной-члена Activity
.Таким образом, я могу вызвать cancel(true)
и надеяться, что это «остановит» задачи.
РЕШЕНИЕ :
В случае, если кто-то ищет что-то подобное - ни одно из упомянутых здесь решений не работает удовлетворительно.Все они страдают от OutOfMemory
проблем.Я не отлаживал детали OOM, но подозреваю, что это может быть либо из-за рекурсии, либо из-за того, что связанные с HTTP объекты являются переменными-членами в AsyncTask
, а не членами Activity
(в основномиз-за НЕ повторного использования HTTP и других объектов).
Я отбросил этот подход для другого - бесконечно совершать мои Ajax-вызовы в doInBackground()
моего AsyncTask
;и обновление пользовательского интерфейса в onProgressUpdate()
.Таким образом, я также избегаю лишних затрат на поддержание слишком большого количества потоков или Handler
с для обновления пользовательского интерфейса (помните, что пользовательский интерфейс может быть обновлен в onProgressUpdate()
).
Этот подход также устраняет необходимость в Timer
си TimerTask
с, предпочитая использовать вместо Thread.sleep()
. Этот поток в SO содержит больше деталей и фрагмент кода.