Updating a ProgressBar in a RecyclerView

I have a RecyclerView. In it, the items have a standard layout - one TextView and one ProgressBar. Items are added to the recyclerview at runtime. Whenever an Item is added, an AsyncTask is started which updates the ProgressBar. The AsynTask holds a reference to the ProgressBar object from the RecyclerView Adapter. The problem occurs when there are too many items in the recycler view.

I know the RecyclerView recycles any old views and thus want a way around that atleast for the progressbars.

What would be the ideal way to implement this?

Following is an excerpt from the Adapter

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();
    }

Also, I'm adding items to the RecyclerView using notifydatasetchanged.

 

4

A little late, but I found a way to get it working.

My recyclerview contains a large number viewholders and only one of the viewholders have a progress bar. I have an sqlite database in which I maintain identifiers which I use to sync between my service and activity (to identify which views in the recyclerview need updating).

Depending on your implementation, you will have to find a way to identify which broadcast event corresponds to which adapter item. I have given a simplified version of what I have done below.

Model for Progress Bar:

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

public int getProgress(){
    return progress;
}

ViewHolder:

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;
    }   
}

In the recyclerview adapter,

@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);
}

In the Activity which implements populates the view, create a static instance of itself and pass it to the BroadcastReceiver. It took me quite a while to figure out that the static instance is required, otherwise the view doesn't get changed even though I call 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);
        }
    }

}

Hope this helps.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值