【问题标题】:Fail to AsyncTask update progressBar's progress when first enter the fragment ListView, then okay after scroll ListView第一次进入片段ListView时AsyncTask更新progressBar的进度失败,滚动ListView后就ok了
【发布时间】:2017-02-02 09:57:50
【问题描述】:

如果没有向下滚动并再次返回相同的位置访问,进度条将无法显示进度,详细请查看此演示:

https://www.youtube.com/watch?v=wGu8MyUHidQ&feature=youtu.be

没有异常或错误,可能是 ListView 错误或逻辑错误,有人知道吗?

DownloadInfo 类:

private final static String TAG = DownloadInfo.class.getSimpleName();
public enum DownloadState {
    NOT_STARTED,
    QUEUED,
    DOWNLOADING,
    COMPLETE
}
private volatile DownloadState mDownloadState = DownloadState.NOT_STARTED;
private final String mFilename;
private volatile Integer mProgress;
private final Integer mFileSize;
private volatile ProgressBar mProgressBar;

public DownloadInfo(String filename, Integer size) {
    mFilename = filename;
    mProgress = 0;
    mFileSize = size;
    mProgressBar = null;
}
//Follow by getters & setters

下载InfoArrayAdapter 类:

public class DownloadInfoArrayAdapter extends ArrayAdapter<DownloadInfo> {
private static class ViewHolder {
    TextView textView;
    ProgressBar progressBar;
    Button button;
    DownloadInfo info;
}

public DownloadInfoArrayAdapter(Context context, List<DownloadInfo> objects) {
    super(context, objects);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    final DownloadInfo info = getItem(position);

    ViewHolder holder = null;

    if (null == row) {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = inflater.inflate(R.layout.file_download_row, parent, false);

        holder = new ViewHolder();
        holder.textView = (TextView) row.findViewById(R.id.downloadFileName);
        holder.progressBar = (ProgressBar) row.findViewById(R.id.downloadProgressBar);
        holder.button = (Button) row.findViewById(R.id.downloadButton);
        holder.info = info;
        row.setTag(holder);
    } else {
        holder = (ViewHolder) row.getTag();
        holder.info.setProgressBar(null);
        holder.info = info;
        holder.info.setProgressBar(holder.progressBar);
    }

    holder.textView.setText(info.getFilename());
    holder.progressBar.setProgress(info.getProgress());
    holder.progressBar.setMax(info.getFileSize());
    info.setProgressBar(holder.progressBar);

    holder.button.setEnabled(info.getDownloadState() == DownloadState.NOT_STARTED);
    final Button button = holder.button;
    holder.button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            info.setDownloadState(DownloadState.QUEUED);
            button.setEnabled(false);
            button.invalidate();
            FileDownloadTask task = new FileDownloadTask(info);
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    });
    return row;
}
}

FileDownloadTask 类:

@Override
protected void onProgressUpdate(Integer... values) {
    mInfo.setProgress(values[0]);
    ProgressBar bar = mInfo.getProgressBar();
    if (bar != null) {
        bar.setProgress(mInfo.getProgress());
        bar.invalidate();
    }
}

@Override
protected Void doInBackground(Void... params) {
    Log.d(TAG, "Starting download for " + mInfo.getFilename());
    mInfo.setDownloadState(DownloadState.DOWNLOADING);
    for (int i = 0; i <= mInfo.getFileSize(); ++i) {
        try {
            Thread.sleep(16);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        publishProgress(i);
    }
    mInfo.setDownloadState(DownloadState.COMPLETE);
    return null;
}

@Override
protected void onPostExecute(Void result) {
    mInfo.setDownloadState(DownloadState.COMPLETE);
}

@Override
protected void onPreExecute() {
    mInfo.setDownloadState(DownloadState.DOWNLOADING);
}

在片段中添加点击监听

lvStickerGroup = (ListView) activity.findViewById(R.id.lvStickerGroup);
    List<DownloadInfo> downloadInfo = new ArrayList<DownloadInfo>();
    for (int i = 0; i < 50; ++i) {
        downloadInfo.add(new DownloadInfo("File " + i, 1000));
    }

    adapter = new DownloadInfoArrayAdapter(activity, downloadInfo);
    lvStickerGroup.setAdapter(adapter); 
    lvStickerGroup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            Toast.makeText(activity, "bla" + i, Toast.LENGTH_SHORT).show();
        }
    });

    //Testing all below, no luck
    ((BaseAdapter) adapter).notifyDataSetChanged();
    lvStickerGroup.invalidate();
    lvStickerGroup.invalidateViews();
    lvStickerGroup.refreshDrawableState();

    lvStickerGroup.post(new Runnable() {
        public void run() {
            for (int a = 0; a < lvStickerGroup.getCount(); a++) {
                lvStickerGroup.setSelection(a);
            }
            for (int a = lvStickerGroup.getCount() - 1; a >= 0; a--) {
                lvStickerGroup.setSelection(a);
            }
        }
    });

我尝试以编程方式滚动到底部并返回顶部,同样没有运气,除了在最初输入片段时以编程方式滚动到项目位置不会显示在第一页中。

另外,我尝试在适配器上invalidate()、invalidateView() notifyDataSetChanged,出现同样的问题,可能是ListView bug?

提前致谢。

【问题讨论】:

  • 你的视频有什么奇怪的地方?请具体。
  • 第一次进入显示ListView的fragment在触发按钮后不会更新进度条,只有向下滚动回到同一个item只有进度条才会显示进度。进度条只是使用一些简单的增量进行测试,睡眠时间为 16 毫秒,它从 ayncTask 更新回 UI...
  • 访问minimal reproducible example并按比例编辑您的问题。
  • 对不起,我知道我的问题太宽泛了,我已经尽力了,无法记录任何异常...我尝试了几天在 ListView 中实现平滑的进度条,最后我找到了代码github,但真的不知道为什么不能在片段中实现,在活动中按预期工作......:/
  • 这是很多代码,没有解释你正在尝试什么或你正面临的问题。请添加一些文本来解释您期望什么以及运行代码时发生的情况。您可能想显示一些屏幕截图以帮助我们更好地解释。

标签: android listview android-fragments android-asynctask android-progressbar


【解决方案1】:

上面的代码没有错,功能齐全。我在 Google ListView IO 大会上找到了线索

https://www.youtube.com/watch?v=wDBM6wVEO70

ListView 不能包装内容,否则会出现错误。这就是我遇到此类问题的原因。

【讨论】:

    猜你喜欢
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    相关资源
    最近更新 更多