在RecyclerView中更新ProgressBar

Pra*_*tye 10 android android-recyclerview

我有一个RecyclerView.其中,项目具有标准布局 - 一个TextView和一个ProgressBar.项目在运行时添加到recyclerview.每当添加一个Item时,都会启动一个更新ProgressBar的AsyncTask.AsynTask保存了RecyclerView Adapter对ProgressBar对象的引用.当回收器视图中的项目太多时,会发生此问题.

我知道RecyclerView会回收任何旧视图,因此想要了解至少进度条的方法.

实现这个的理想方法是什么?

以下是适配器的摘录

public class RecViewAdapter extends
        RecyclerView.Adapter<RecViewAdapter.ViewHolder> {
    Context mContext;
    List<String> mRunns;
    static ExecutorService mExec;
    static HashSet<Integer> mProcessed = new HashSet<>();

    public RecViewAdapter(Context context, List<String> runns) {
        mContext = context;
        mRunns = runns;
        mExec = Executors.newFixedThreadPool(1);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.runnabel_item, viewGroup,
                false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.runnName.setText(mRunns.get(position));
        if (!mProcessed.contains(position)) {
            new ProgressTask(holder.pBar, position).executeOnExecutor(mExec, null);
            mProcessed.add(position);
        }
    }

    @Override
    public int getItemCount() {
        return mRunns.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView runnName;
        ProgressBar pBar;

        public ViewHolder(View view) {
            super(view);
            runnName = (TextView) view.findViewById(R.id.textView);
            pBar = (ProgressBar) view.findViewById(R.id.progressBar);
            pBar.setIndeterminate(false);
            pBar.setMax(100);
            pBar.setProgress(0);

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,我使用notifydatasetchanged将项目添加到RecyclerView.

May*_*rma 7

您可以简单地使用回收器视图的“findViewHolderForAdapterPosition”方法,您将从中获得一个 viewHolder 对象,然后将该 viewHolder 类型转换为您的适配器视图,这样您就可以直接访问您的视图持有者的视图,(在这种情况下,我们访问 progressBar)

以下是 kotlin 的示例代码

 /**
     * update progress bar in recycler view
     * get viewHolder from position and progress bar from that viewHolder
     *  we are rapidly updating progressbar so we did't use notify method as it always update whole row instead of only progress bar
     *  @param position : position of list cell
     *  @param progress : new progress value
     */
    private fun updateDownloadProgressBar(position :Int, progress:Int)
    {
        val viewHolder = recyclerViewDownload.findViewHolderForAdapterPosition(position)
        (viewHolder as ViewHolderDownload).progressBarDownload.progress=progress
    }
Run Code Online (Sandbox Code Playgroud)


mUs*_*990 4

有点晚了,但我找到了一种让它发挥作用的方法。

我的 recyclerview 包含大量视图持有者,并且只有一个视图持有者有进度条。我有一个 sqlite 数据库,在其中维护标识符,用于在服务和活动之间同步(以识别 recyclerview 中的哪些视图需要更新)。

根据您的实现,您必须找到一种方法来识别哪个广播事件对应于哪个适配器项。我在下面给出了我所做工作的简化版本。

进度条模型:

class ProgressModel{
    String progressId;
    int progress = 0;
}

public int getProgress(){
    return progress;
}
Run Code Online (Sandbox Code Playgroud)

视图持有者:

public class ProgressViewHolder extends RecyclerView.ViewHolder {
    private ProgressBar mProgressBar;

    public ProgressViewHolder(View itemView) {
        mProgressBar = (ProgressBar) itemView.findViewById(R.id.mProgressBar);
    }

    public ProgressBar getProgressBar() {
        return mProgressBar;
    }   
}
Run Code Online (Sandbox Code Playgroud)

在recyclerview适配器中,

@Override
public void onBindViewHolder(ProgressViewHolder holder, int position) {
    ProgressModel item = mData.get(position);
    int progress = item.getProgress();
        if (progress > 0) {
            ProgressBar downloadProgress = holder.getProgressBar();
            if (downloadProgress.isIndeterminate()) {
                downloadProgress.setIndeterminate(false);
            }
            downloadProgress.setProgress(progress);
        }
}

public void refresh(position, ProgressModel item){
    mData.set(position, item);
    notifyItemChanged(position);
}
Run Code Online (Sandbox Code Playgroud)

在实现填充视图的 Activity 中,创建其自身的静态实例并将其传递给 BroadcastReceiver。我花了很长时间才弄清楚静态实例是必需的,否则即使我调用notifyItemchanged(),视图也不会改变。

public class MainActivity extends Activity{
    private static MainActivity instance;
    private MyReceiver mReceiver;
    private MyAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        instance = this;
        mReceiver = new MyReceiver(instance);
        //TODO: Initialize adapter with data and set to recyclerview
    }

    public void update(Intent intent){
        ProgressModel model = new ProgressModel ();
        //TODO: set progress detail from intent to model and get position from progressId
        instance.mAdapter.refresh(position,model);
    }

    private static class MyReceiver extends BroadcastReceiver {
        MainActivity activity;

        public DownloadReceiver(MainActivity activity) {
            this.activity = activity;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            //pass intent with progress details to activity
            activity.update(intent);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。