Показать определенный ProgressBar в onProgressUpdate AsyncTask в течение времени, необходимого для загрузки данных из Интернета

Я пытаюсь использовать эту библиотеку для публикации хода выполнения на экране Activity в onProgressUpdate() AsyncTask, который используется для загрузки некоторых данных из Интернета. Демонстрационное приложение, которое они предоставили, использует Handler для демонстрации этого. Мне нужно использовать его в AsyncTask.

Следующий фрагмент кода взят из кода их демо-приложения.

Мои вопросы:

  1. onProgressUpdate получает аргумент Progress... values и согласно документации, это «значения, указывающие на прогресс». Но я не понимаю, что это значит и как мне использовать этот аргумент. В примерах, которые я видел, они делают что-то вроде:

    progressBar.setProgress(Integer.parseInt(values[0]));
    

    Почему они используют только первое значение в переданном массиве (значения[0])?

  2. Откуда AsyncTask знает, сколько времени потребуется для завершения операции загрузки. Я хочу показать прогресс ProgressBar от значения 0 до 100 в течение времени, затраченного на завершение операции загрузки.

    Выполняя progressBarDeterminate.setVisibility(View.VISIBLE) в onPreExecute и выполняя progressBarDeterminate.setVisibility(View.GONE) в onPostExecute, мы гарантируем, что они будут отображаться только тогда, когда данные загружаются, но как мы можем гарантировать, что они перемещаются из начальной позиции в конечную в течение времени, которое требуется для загрузки данных (когда мы точно не знаем, сколько времени потребуется для загрузки данных) ?

КОД ИЗ ДЕМО ПРИМЕРА (используется обработчик, но мне нужно сделать это в AsyncTask)

public class MainActivity extends AppCompatActivity {
    ProgressBarDeterminate progressBarDeterminate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        progressBarDeterminate = (ProgressBarDeterminate) findViewById(R.id.progressDeterminate);

        progressTimer.start();
    }


        Thread progressTimer = new Thread(new Runnable() {

                @Override
                public void run() {
                    for(int i = 0; i <= 100; i++){
                        try {
                            Thread.sleep(30);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        handler.sendMessage(new Message());
                    }
                }
            });

            Handler handler = new Handler(new Handler.Callback() {
                int progress = 0;
                @Override
                public boolean handleMessage(Message msg) {
                    progressBarDeterminate.setProgress(progress++);
                    return false;
                }
            });
}

person Solace    schedule 20.08.2015    source источник


Ответы (1)


Отвечая на ваш первый вопрос, onProgressUpdate() принимает аргумент varargs. Это означает, что он может принимать неопределенное количество аргументов указанного типа. Например:

public void someMethod(String... args) {
    //...
}

Может называться так, someMethod("Hi!"), или так someMethod("Hi", "there", "welcome", "to", "SO").

Дополнительную информацию о varargs можно найти здесь. Доступ к этим аргументам осуществляется так же, как к массиву. Если там только один аргумент, вы можете использовать args[0].

Редактировать: Что касается вашего второго вопроса, хороший пример из всех представлен в Android Developers javadocs:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

А именно, ответ действительно зависит от ваших обстоятельств. Скажем, в приведенном выше примере вам нужно загрузить десять URL-адресов. Цикл for настроен на загрузку каждого URL последовательно, и как только URL завершится, вызывается publishProgress(), превращая текущее значение в процентную цифру (i / (float) count) * 100). Надеюсь, это ответ на ваш вопрос!

person PPartisan    schedule 20.08.2015
comment
Поскольку doInBackground принимает аргумент типа varargs, вы можете обращаться с urls так же, как с массивом (то есть с объектом URL[]). Итак, он имеет длину и URL членов. - person PPartisan; 20.08.2015
comment
В моем приложении в doInBackground данные поступают из веб-службы, и они имеют сложный тип (подобный JSON), а затем я анализирую их, прежде чем возвращать из doInBackground. Поэтому я понятия не имею, как мне узнать количество итераций, которое должен выполнять цикл for (т.е. переменная count). Можете ли вы что-нибудь предложить? - person Solace; 20.08.2015
comment
Я разместил первый комментарий до того, как вы отредактировали вопрос, и после вашего редактирования на мой вопрос был дан ответ. Поэтому я удалил комментарий. - person Solace; 20.08.2015
comment
@Solace Боюсь, что нет, извините, я никогда не работал с JSON в Android. - person PPartisan; 20.08.2015
comment
Нет проблем, и большое спасибо за ваш ответ. Я собираюсь принять это. Я предполагаю, что я буду вызывать publishProgress трижды, перед вызовом веб-сервиса, после того, как данные пришли и до их анализа, после их анализа. - person Solace; 20.08.2015
comment
@Solace Это сработает. Помните также, что если ваша ситуация не подходит для панели обновлений в процентном стиле, вы можете вернуть что угодно из publishProgress(), а не только Integer. Это может быть String для сообщения, значение ресурса изображения и т. д. - person PPartisan; 20.08.2015