Как разрешить Asynctask обновлять пользовательский интерфейс различными способами - PullRequest
3 голосов
/ 15 апреля 2011

Это проблема, с которой я часто сталкиваюсь при использовании Asyntask.Чтобы связаться с потоком пользовательского интерфейса, нужно вызвать publishProgress (), и этот метод принимает массив только с одним параметром TYPE .

Потоку, работающему в фоновом режиме и выполняющему сложные вычисления, может потребоваться обновить пользовательский интерфейс в разных точках, используя различные типы объекта.

Позвольте мне проиллюстрировать это на примере:

...do some processing...
// Send UI thread the integer values of the width & height of the image 
...do some more processing...
// Send UI thread a String with custom message.
...do some more processing...
// Send UI thread an instance of MyObject so it can extract & display certain values 
...do some cleanup job & finish...

Однако onProgressUpdate () принимает массив только одного типа.

Поэтому я могу сделать это всеобъемлющим Объект Тип?Как я знаю, как преуменьшить его, так как этот метод может быть вызван из строки 1, 2 или 3, который сейчас час?

Наверняка должен быть хороший способ добиться этого?

РЕДАКТИРОВАТЬ: То, что я действительно хотел бы видеть, если бы это было возможно в Android, было бы каким-то образом определить publishProgress1 (пользовательские args1) , publishProgress2 (пользовательские args2) , publishProgress3 (пользовательские args3) ...

Ответы [ 5 ]

4 голосов
/ 15 апреля 2011

В вашем третьем случае ...

// Отправить поток пользовательского интерфейса экземпляр MyObject

... есть аргумент, чтобы вы сделали это вonPostExecute (), хотя это зависит от того, что вы имели в виду на своей иллюстрации.

Вы можете легко сделать, как вы предлагаете, передавая все охватывающие объекты.У объекта могут быть различные поля (целое число, строка, объект) плюс «действие», которое необходимо предпринять, описывающее, какие из этих полей являются действительными и должны быть обработаны.

Вы можете просто передать int enum, такой как PROCESS_INT_WIDTH_AND_HEIGHT, PROCESS_STRING_MESSAGE, PROCESS_OBJECT и т. Д. Ничто не мешает вам сделать это ...

private static class MyAsyncTask extends AsyncTask<String, int, Void> {
    private int width;
    private int height;
    private String customMessage;
    private MyObject myObject;

    @Override
    protected Void doInBackground(String... params) {

        width = 10;
        height = 10;
        publishProgress(PROCESS_INT_WIDTH_AND_HEIGHT);
    }

    protected void onProgressUpdate(int... progress) {
        if (progress == PROCESS_INT_WIDTH_AND_HEIGHT)
            // Process width and height
    }
}

Другими словами, метод onProgressUpdate () просто отвечает на команду и обрабатывает соответствующиечастные поля соответственно.

2 голосов
/ 15 апреля 2011

Если вы хотите придерживаться AsyncTask , другой вариант - использовать другой класс в разное время и тестировать тип с instanceof.

Однако это звучит как довольно сложная задача, поэтому я бы посоветовал взглянуть на использование Handler и опубликовать его [Runnable] s 2 из обычной темы или с помощью runOnUiThread .

Возможно, вы также захотите прочитать Безболезненная заправка

Надеюсь, это поможет,

Фил Лелло

0 голосов
/ 15 апреля 2011

Если возвращаемые значения имеют соответствующее состояние при обработке AsyncTask, вы можете создать закрытый элемент внутри AsyncTask для каждого необходимого типа / типа, а затем присвоить целое число каждому состоянию и в onProgressUpdate(Integer...) поставить switch(state), который выполняет работу в зависимости от состояния int, полученного из publishProgress(state).

(это может быть не самый ясный ответ, который я дал)

0 голосов
/ 15 апреля 2011

Будет ли универсальный тип работать в этом сценарии?Вы можете ввести значения по мере необходимости.Пример AsyncTask прототип:

new AsyncTask<String, Object, List<?>>(){ 
...

Я также вспоминаю, что AsyncTask наиболее подходит только для коротких задач.Рассмотрим другие модели потоков для сложных и длительных операций.

0 голосов
/ 15 апреля 2011

Я не думаю, что есть другой способ сделать это. Создайте базовый класс с помощью метода getType, а затем используйте его как тип для соответствующего приведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...