当我们使用地图功能实时跟踪设备位置的时候,一般会希望保证可以显示最新位置。但也有可能操作者希望确认周边信息而暂时脱离最新位置,等周边信息确认完成之后再自动回到最新位置。
动作视频如下:
我们通过发布异步延迟派发任务来实现这个功能。
计算无操作时间
我们准备一个定时器,每当用户对屏幕进行操作时更新最后操作时刻。
代码语言:javascript复制
代码语言:javascript复制void resetOperationTimer(){
lastOperation = Calendar.getInstance().getTimeInMillis();
}
在需要检查时,将当前时刻和最后的操作时刻进行比较就可以判断是否超过操作延时时长了。
代码语言:javascript复制
代码语言:javascript复制boolean isOperationTimeout(){
return (Calendar.getInstance().getTimeInMillis() - lastOperation) > operationTimeout;
}
发布异步延迟派发任务
在重置最后操作时刻时我们同时发行一个异步延迟派发任务:
代码语言:javascript复制
代码语言:javascript复制void reserveInvalidate(){
TaskDispatcher uiTaskDispatcher = mContext.getUITaskDispatcher();
Revocable revocable = uiTaskDispatcher.delayDispatch(new Runnable() {
@Override
public void run() {
visibleAreaCheck();
}
}, operationTimeout);
}
void visibleAreaCheck(){
//如果最新位置超出显示位置
if (lastLocation != null && isOperationTimeout()){
Rect bound = new Rect(0, 0, getWidth(), getHeight());
Size offset = Tile.calculateOffset(512, zoom, location, lastLocation);
int x = getWidth() / 2 offset.width;
int y = getHeight() / 2 offset.height;
if(!bound.isInclude(x, y)) {
location = lastLocation;
invalidate();
}
}
}
有几点需要注意:
- 这个任务是发布到UI线程的,这样的好处是不必考虑多线程之间的上下文切换。
- 如果在进行可视范围检查时,时间差没有达到事先指定的时长,那就意味着中间又发生了新的操作,则本次检查取消。也就是说,只要操作继续就不会发生显示位置重置。