【问题标题】:Updating ProgressBar from AsyncTask lagging UI从 AsyncTask 滞后 UI 更新 ProgressBar
【发布时间】:2016-09-26 16:04:05
【问题描述】:

我有一个Fragment 和一个RecyclerView,而RecyclerViewViewHolder 持有一个ProgressBar 以显示下载过程的进度。

public static class ViewHolder extends RecyclerView.ViewHolder {
    ....
    private ProgressBar progressBar = null;
    ....
    public ViewHolder(View itemView) {
        super(itemView);

        ....
        this.progressBar = (ProgressBar) itemView.findViewById(R.id.progessbar);
        ....
    }
}

我为我的Fragment 创建了一个回调:

public interface CallbackItemChanged {
    void onItemChanged(final int position);
}

如果它被调用,我会这样做:

@Override
public void onItemChanged(final int position) {
    this.adapter.notifyItemChanged(position);
}

在我的AsyncTask:

protected void onProgressUpdate(Integer... progress) {
    super.onProgressUpdate(progress);

    this.entry.setProgress(progress[0]);
    this.entry.setProgressString(progress[0] + "%");

    this.callbackItemChanged.onItemChanged(this.entry.getPosition());
}

进度已成功发布,但用户界面非常滞后,但我不知道为什么? onProgressUpdate 是在 ui 线程上运行的不是吗?我觉得应该是这样还是我错了?

如何在更新进度条时让 ui 顺利运行?

编辑

@Override
protected String doInBackground(Void... params) {
    this.inputStream = null;
    this.outputStream = null;
    this.connection = null;

    File file = new File(this.entry.getPath(this.context));
    File parent = file.getParentFile();

    try {
        parent.mkdirs();
        file.createNewFile();

        this.connection = (HttpsURLConnection) new URL(this.entry.getUrl()).openConnection();
        this.connection.connect();

        int fileLength = this.connection.getContentLength();

        this.inputStream = this.connection.getInputStream();
        this.outputStream = new FileOutputStream(file);

        byte data[] = new byte[4096];
        long progress = 0;
        int count;

        while ((count = this.inputStream.read(data)) != -1) {
            if (this.isCancelled() || this.entry.isCancelled()) {
                this.handleClose();
                this.handleDelete();

                return null;
            }

            if (fileLength > 0) {
                this.publishProgress((int) ((progress +=count) * 100 / fileLength));
            }

            this.outputStream.write(data, 0, count);
        }
    } catch (Exception e) {
        this.handleDelete();

        return e.toString();
    } finally {
        this.handleClose();
    }

    return null;
}

【问题讨论】:

  • 请向我们展示您的整个 AsyncTask 代码。我们需要看看您是如何使用 publishProgress 方法发布进度的。
  • 您可能会用进度更新淹没 UI,但如果没有任何代码表明您发布进度的时间和频率,我们对此无话可说。当您说“用户界面像地狱一样滞后”时,您的意思是用户界面在滚动时出现卡顿,或者可能是其他更量化的东西?
  • 我添加了我的doInBackground 以显示我在哪里使用publishProgress。是的,用户界面在滚动时卡顿。

标签: android android-asynctask android-progressbar


【解决方案1】:

您在循环中发布进度,因此您的主线程将被调用很多次。

您可以使用简单的 Thread.sleep() 延迟发布进度:

    while ((count = this.inputStream.read(data)) != -1) {
        if (this.isCancelled() || this.entry.isCancelled()) {
            this.handleClose();
            this.handleDelete();

            return null;
        }

        // Write the data before publishing the progress
        this.outputStream.write(data, 0, count);

        try{
            // Adjust this value. It shouldn't be too small.
            Thread.sleep(100);
        }catch (InterruptedException e){
            // Nothing you can do here
        }finally {
            if (fileLength > 0) {
                this.publishProgress((int) ((progress +=count) * 100 / fileLength));
            }
        }
    }

或者您只能以 x% 为增量发布:

while ((count = this.inputStream.read(data)) != -1) {
    if (this.isCancelled() || this.entry.isCancelled()) {
        this.handleClose();
        this.handleDelete();

        return null;
    }

    // Write the data before publishing the progress
    this.outputStream.write(data, 0, count);

    if (fileLength > 0) {
        currentProgress = ((progress += count) * 100 / fileLength);
        // Publish only on increments of 1%
        if (currentProgress >= previousProgress + 1) {
            this.publishProgress(currentProgress);
            previousProgress = currentProgress;
        }

    }
}

【讨论】:

  • 这不会减慢下载过程吗?
  • 是的。另一种方法是仅当您与之前的进度有一定差异时才发布。我会用一个例子来编辑我的答案。
猜你喜欢
  • 1970-01-01
  • 2014-08-21
  • 2021-04-04
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多