Как обновить относительное время в утилитарике? - PullRequest
2 голосов
/ 31 марта 2019

У меня есть RecyclerView, который отображает элементы с заголовком, текстом и временем последнего редактирования. enter image description here

В onBindViewHolder адаптера RecyclerView я использую 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 предложил следующий вопрос: Обновление относительного времени в Android , однако я не думаю, что обновление RecyclerView каждые X секунд - лучшая идея:

  1. разряжает батарею
  2. обновляет элементы, которые не нуждаются в обновлении (например, последнее обновление было сделано 6 часов назад, но оно обновляется holder.timestamp каждые Х секунд)

Есть ли более эффективный способ сделать это?

1 Ответ

4 голосов
/ 31 марта 2019

Поскольку вам нужно обновлять пользовательский интерфейс только тогда, когда он виден, вы можете уменьшить расход заряда батареи, обновляя свой пользовательский интерфейс только тогда, когда вы знаете, что он находится на переднем плане, используя обратные вызовы жизненного цикла onResume() и onPause() в вашем фрагменте / активности. Кроме того, если для вашего случая достаточно мелкой детализации, вы можете использовать системную трансляцию 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);
       }
    }
}
...