Android: создать фоновый поток, который периодически запускается и выполняет задачи пользовательского интерфейса?
Итак, я знаю, как выполнить фоновую задачу, я знаю, как выполнить периодическую задачу (используя handle postdelayed и runnable), я также знаю, как выполнить задачу пользовательского интерфейса из фонового потока (через обработчик), но я не могу выполнить периодическую фоновую задачу, которая выполняет некоторые действия в потоке пользовательского интерфейса.
Я каждую минуту пытаюсь выполнить какую-то фоновую задачу, в которой мне нужно сделать сетевой вызов. После завершения вызова, в зависимости от выходных данных, я должен обновить пользовательский интерфейс. Я попытался сделать что-то вроде это
private void DoTask() {
Thread thread = new Thread() {
public void run() {
Looper.prepare();
final Handler handler = new Handler();
handler.post(netRunnable);
Looper.loop();
}
};
thread.start();
}
Runnable netRunnable = new Runnable() {
@Override
public void run() {
handler.getLooper().prepare();
final Handler handler1 = new Handler(Looper.getMainLooper());
if ( do background work and check result){
handler1.post(new Runnable() {
@Override
public void run() {
//Do UI Task
}
});
}
handler.getLooper().loop();
handler.postDelayed(netRunnable, 60000);
}
}
Я понимаю, что в моей реализации могут быть некоторые фундаментальные недостатки, но я не знаю, как правильно выполнить эту задачу. Прямо сейчас он дает ошибку, которая Only one Looper may be created per thread
.Я понимаю, что он пытается сказать. Но может ли кто-нибудь, пожалуйста, предложить сделать это правильно.3 ответа:
Может быть, вам лучше создать отдельный (Intent)Сервис и периодически вызывать его с помощью postDelayed. Создайте BroadcastReceiver в своей активности и обрабатывайте изменения пользовательского интерфейса там.
Еще одна подсказка для обработки изменений пользовательского интерфейса из других потоков: это невозможно. Поэтому вам нужно вызвать runOnUiThread. Вот как его использовать
Можно использовать асинхронные задачи. Они предназначены для этого:
Http://developer.android.com/reference/android/os/AsyncTask.html
Он позволяет выполнить сетевой вызов в фоновом режиме, а затем, когда вы получите результат, выполнить действие в потоке пользовательского интерфейса
Объявление:
private class MyTask extends AsyncTask<Input, Void, Output> { protected Output doInBackground(Input... inputs) { // do something on the network return myOutput;// use this to transmit your result } protected void onPostExecute(Output result) { // do something on UI thread with the result }
}
Если вы хотите повторить его, просто создайте runnable, чтобы запустить его, и после каждого вызова запланируйте следующий:
MyTask myTask; Handler handler = new Handler(); Runnable myRunnable = new Runnable() { @Override public void run() { MyTask myTask = new MyTask(); myTask.execute(myArg); handler.postDelayed(netRunnable, 60000); // schedule next call } }
Чтобы запустить его в первый раз :
handler.postDelayed(myRunnable, 60000);
Или, если вы хотите запустить его немедленно:
handler.post(myRunnable);
Не забудьте отменить задание, когда ваша активность будет уничтожена:
myTask.cancel(true);
Если деятельность часто меняется, почему бы не поменять местами обязанности. Можно создать службу, выполняющую периодические сетевые задачи.
Тогда, - либо ваша деятельность периодически вызывает этот сервис, чтобы получить значение. - или вы используете систему прослушивания: вы создаете интерфейс, который ваши действия должны реализовать, чтобы получать уведомления от завершения задачи