user3806331 user3806331 - 14 days ago 14
Android Question

recyclerview periodic ui child updates

I have a recyclerView of items that, (among others), contains a timeStamp of a duration of a game retrieved from a WS. To show the duration of the match, i have to get the current timeStamp, do the mat and convert it to a readable format (for eg: 5 minutes 5s). Only some of the views need to be updated.

Each childview needs to be updated every xxx seconds.


  • My first aproach was create a list of Objects binded to the view that needed to be updated. On my fragment i would declare a Handler and call notifyItemChanged(position) for every object in the list. Each time the handler calls notifyItemChanged, the whole view is re-rendered, and there's a small blink effect. I don't want it to happen, so my second approach was to only change the TextView of every childView that needed to be updated. Here is the code:

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
    if (needsUpdate) {
    holder.startRepeatingTask();
    } else {
    holder.stopRepeatingTask();
    }
    }
    class MyViewHolder extends RecyclerView.ViewHolder {
    private final int mHandlerInterval = 6000;
    private Handler mHandler;
    private Runnable mStatusChecker;

    public MyViewHolder(View itemView) {
    super(itemView);
    ButterKnife.inject(this, itemView);
    mHandler = new Handler();
    mStatusChecker = new Runnable() {
    @Override
    public void run() {
    String gameStatusToPrint = current.getGameStatusToPrint();
    gameStatus.setText(gameStatusToPrint);
    mHandler.postDelayed(mStatusChecker, mHandlerInterval);
    }
    };
    }

    public void startRepeatingTask() {
    mStatusChecker.run();
    }

    public void stopRepeatingTask() {
    mHandler.removeCallbacks(mStatusChecker);
    }
    }



I'm not sure if this is the best approach and need recommendation on this.

Answer

As the ViewHolder is going to be recycled by the RecyclerView. You'll need to make sure you're maintaining the stability between the "current game" and the item shown on the list. Despite that i think your solution is fine.

Here's the fix for that:

@Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

        holder.game = mGameList.get(position);
        if (needsUpdate) {
            holder.startRepeatingTask();
        } else {
            holder.stopRepeatingTask();
        }
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        private final int mHandlerInterval = 6000;
        private Handler mHandler;
        private Runnable mStatusChecker;

        public Game game;

        public MyViewHolder(View itemView) {
            super(itemView);
            ButterKnife.inject(this, itemView);
            mHandler = new Handler();
            mStatusChecker = new Runnable() {
                @Override
                public void run() {
                    String gameStatusToPrint = game.getGameStatusToPrint();
                    gameStatus.setText(gameStatusToPrint);
                    mHandler.postDelayed(mStatusChecker, mHandlerInterval);
                }
            };
        }

        public void startRepeatingTask() {
            mStatusChecker.run();
        }
Comments