如何在recyclerview中更新相对时间?

时间:2019-03-31 12:24:00

标签: java android android-recyclerview android-dateutils

我有一个RecyclerView,它显示带有标题,文本和上次编辑时间的项目。 enter image description here

在RecyclerView适配器的onBindViewHolder中,我使用getRelativeTimeSpanString并将注释对象的时间与当前时间进行比较:

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    Note note = getItem(position);
    holder.title.setText(note.getTitle());
    holder.text.setText(note.getText());

    String s = DateUtils.getRelativeTimeSpanString(note.getTime(), 
    System.currentTimeMillis(), 0L, DateUtils.FORMAT_ABBREV_ALL).toString();
    holder.timestamp.setText(s);
}

如果我刚刚添加了该项目,它会显示“ 0秒前”。我如何随着时间的推移更新它?

在撰写此问题的同时,提出了以下问题:Updating the relative time in android,但是我认为最好不要每隔X秒更新RecyclerView:

  1. 耗尽电池电量
  2. 它会更新不需要更新的项目(例如, 上次更新是6小时前,但它正在更新holder.timestamp 每X秒)

有没有更有效的方法来实现这一目标?

1 个答案:

答案 0 :(得分:4)

鉴于您只需要在可见时更新UI,就可以通过在您的UI中使用onResume()onPause()生命周期回调,仅在知道UI处于前台时才更新UI来减少电池消耗片段/活动。另外,如果分钟粒度足以满足您的用例,则可以使用ACTION_TIME_TICK系统广播,该广播每分钟触发一次,因此您不需要不必要地创建自己的计时器。

首先,在BroadcastReceiver中注册onResume()以收听此广播,然后在onPause()中取消注册:

@Override
public void onResume() {
    final IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_TICK);
    getContext().registerReceiver(receiver, filter);
}

@Override
public void onPause() {
    getContext().unregisterReceiver(receiver);
}

receiver内,包含用于更新RecyclerView相关项目(或将其委托给Adapter的逻辑),作为一个粗略的示例:

final BroadcastReceiver receiver = new BroadcastReceiver() {
   @Override
   public void onReceive(Context context, Intent intent) {
      adapter.updateTimes();
   }
}

//Inside your Adapter...
void updateTimes() {
    for(int i = 0; i < notes.size(); i++) {
       final Note note = notes.get(i);
       //Pseudocode for determening whether or not an update it necessary
       //Actual implementation will depend on how you handle updates
       final String relative = getCurrentRelativeTimeString(); 
       if(!Objects.equals(relative, note.getRelativeTimeString())) {
           note.setRelativeTimeString(relative);
           notifyItemChanged(i);
       }
    }
}