3

我有一个 RecyclerView,它显示带有标题、文本和上次编辑时间的项目。 在此处输入图像描述

在 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 秒前”。我如何随着时间的推移更新它?

在写这个问题时,SO提出了这个问题:Updating the relative time in android,但是我不认为每X秒更新一次 RecyclerView 是最好的主意:

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

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

4

1 回答 1

7

鉴于您只需要在 UI 可见时更新它,您可以通过仅在您知道 UI 处于前台时使用Fragment/Acitvity 中的onResume()和生命周期回调来更新您的 UI 来减少电池消耗。onPause()此外,如果分钟粒度对您的用例来说足够好,您可以使用ACTION_TIME_TICK每分钟触发一次的系统广播,因此您无需创建自己的计时器。

首先,在 中注册 aBroadcastReceiver以收听此广播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);
       }
    }
}
于 2019-03-31T14:15:10.513 回答