Как обновить индикатор прогресса в элементе ListView

У меня есть ListView, прикрепленный к ArrayAdapter. Когда пользователь нажимает кнопку загрузки для элемента в ListView, загрузка начинается с DownloadManager.

Что я хочу сделать, так это отслеживать ход загрузки с индикатором выполнения (помещается в макет элемента). Как это можно достичь?

Как работает Pocket Cast, это то, чем я занимаюсь:

Карманный экземпляр каста http://www.mrcrab.net/images/thumb_big/9982-Pocket_Casts_Apk_v4.3.2_Android-0.jpg

Примечание. Я знаю, как работать с DownloadManager, это мгновенное обновление строки выполнения, которая является сложной.

Ответы

Ответ 1

Так я окончательно решил это (после многих итераций и разных реализаций). Это немного сложно, но в основном вам нужны три вещи:

  • AsyncTask, который собирает метаданные
  • Слушатель прокрутки, который сообщает нам, когда пользователь остановил прокрутку/покачивание
  • Умный алгоритм, который находит любую видимую строку, которая нуждается в обновлении, и просит адаптер обновить только эту строку

Именно так я его разработал и внедрил:

Screenshot

Я более подробно описал здесь, и, пожалуйста, просмотрите github code для полного изложения.

    private class UpdaterAsyncTask extends AsyncTask<Void, Void, Void> {

    boolean isRunning = true;

    public void stop() {
        isRunning = false;
    }

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

        while (isRunning) {

            // Gather data about your adapter objects
            // If an object has changed, mark it as dirty                

            publishProgress();

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Void... params) {
        super.onProgressUpdate();

        // Update only when we're not scrolling, and only for visible views
        if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
            int start = mListview.getFirstVisiblePosition();
            for(int i = start, j = mListview.getLastVisiblePosition(); i<=j; i++) {
                View view = mListview.getChildAt(i-start);
                if (((Content)mListview.getItemAtPosition(i)).dirty) {
                    mListview.getAdapter().getView(i, view, mListview); // Tell the adapter to update this view
                }

            }
        }

      }
    }