在列表视图中查看回收导致 postDelayed() 问题
View recycling in listview causes postDelayed() issue
我有一个用户列表 tasks/to-dos,其中有与之关联的截止日期。每分钟我都会更新显示这些任务剩余时间的 TextView
。
我遇到的问题是,有时当 textview 更新时,会显示错误的剩余时间,尤其是当我上下滚动时,另一个任务的剩余时间将出现在它的位置。
我知道这与列表中的视图被回收有关,并且不敬的(屏幕外)视图仍在处理它们的逻辑。我将错误缩小到我的 Runnable
class,其中有时 taskTime
与错误的视图相关联。
我不确定如何用正确的 view
保持正确的 taskTime
,有什么建议吗?
p.s 如何清除不再可见的视图的所有 postDelayed()
?
MyCursorTreeAdapter.class
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
long taskTime = cursor.getLong(cursor.getColumnIndexOrThrow(TableTask.COLUMN_TIME));
viewHolder.timeLeftTextView.setText(TimeUtils.getFormatedTimeLeft(taskTime));
Runnable updateTimeRemainingRunnable = new UpdateTimeRemainingRunnable(view, taskTime);
long postDelay = TimeUtils.millisecondsUntilNextMinute();
view.postDelayed(updateTimeRemainingRunnable, postDelay);
}
private static class UpdateTimeRemainingRunnable implements Runnable {
private final WeakReference<View> weakViewRef;
private final long taskTime;
protected UpdateTimeRemainingRunnable(View view, long taskTime) {
weakViewRef = new WeakReference<>(view);
this.taskTime = taskTime;
}
@Override
public void run() {
final View view = weakViewRef.get();
if (view == null) return;
ViewHolder viewHolder = (ViewHolder) view.getTag();
view.getTag();
// Task time is wrong here -- I sometimes get another task's task time
String formatedTime = TimeUtils.getFormatedTimeLeft(taskTime);
viewHolder.timeLeftTextView.setText(formatedTime);
long postDelay = TimeUtils.millisecondsUntilNextSecond();
view.postDelayed(this, postDelay);
}
}
直接方式,
使用view.setTag(resouce_id,runnable)将runnable和view绑定在一起;
获取ChildView时,首先检查view.getTag(resouce_id),如果不为null,则使用
view.removeCallbacks() 清除它,并重新绑定一个新的 Runnable。
列表视图在滚动时使用回收项...。
但这不是最佳解决方案。
我有一个用户列表 tasks/to-dos,其中有与之关联的截止日期。每分钟我都会更新显示这些任务剩余时间的 TextView
。
我遇到的问题是,有时当 textview 更新时,会显示错误的剩余时间,尤其是当我上下滚动时,另一个任务的剩余时间将出现在它的位置。
我知道这与列表中的视图被回收有关,并且不敬的(屏幕外)视图仍在处理它们的逻辑。我将错误缩小到我的 Runnable
class,其中有时 taskTime
与错误的视图相关联。
我不确定如何用正确的 view
保持正确的 taskTime
,有什么建议吗?
p.s 如何清除不再可见的视图的所有 postDelayed()
?
MyCursorTreeAdapter.class
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
long taskTime = cursor.getLong(cursor.getColumnIndexOrThrow(TableTask.COLUMN_TIME));
viewHolder.timeLeftTextView.setText(TimeUtils.getFormatedTimeLeft(taskTime));
Runnable updateTimeRemainingRunnable = new UpdateTimeRemainingRunnable(view, taskTime);
long postDelay = TimeUtils.millisecondsUntilNextMinute();
view.postDelayed(updateTimeRemainingRunnable, postDelay);
}
private static class UpdateTimeRemainingRunnable implements Runnable {
private final WeakReference<View> weakViewRef;
private final long taskTime;
protected UpdateTimeRemainingRunnable(View view, long taskTime) {
weakViewRef = new WeakReference<>(view);
this.taskTime = taskTime;
}
@Override
public void run() {
final View view = weakViewRef.get();
if (view == null) return;
ViewHolder viewHolder = (ViewHolder) view.getTag();
view.getTag();
// Task time is wrong here -- I sometimes get another task's task time
String formatedTime = TimeUtils.getFormatedTimeLeft(taskTime);
viewHolder.timeLeftTextView.setText(formatedTime);
long postDelay = TimeUtils.millisecondsUntilNextSecond();
view.postDelayed(this, postDelay);
}
}
直接方式,
使用view.setTag(resouce_id,runnable)将runnable和view绑定在一起;
获取ChildView时,首先检查view.getTag(resouce_id),如果不为null,则使用 view.removeCallbacks() 清除它,并重新绑定一个新的 Runnable。
列表视图在滚动时使用回收项...。
但这不是最佳解决方案。