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 2

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);

Если деятельность часто меняется, почему бы не поменять местами обязанности. Можно создать службу, выполняющую периодические сетевые задачи.

Тогда, - либо ваша деятельность периодически вызывает этот сервис, чтобы получить значение. - или вы используете систему прослушивания: вы создаете интерфейс, который ваши действия должны реализовать, чтобы получать уведомления от завершения задачи