如何在定时器中调用LocationListener内置方法 实现间隔10分钟上传位置
问题根因分析
- 重复创建
Timer实例:原代码在每次onLocationChanged触发时都会新建Timer对象,会导致大量重复定时任务并行执行,完全不符合间隔10分钟上传一次的需求 - Timer运行在子线程:
TimerTask的run()方法执行在工作线程,sendLocation()方法涉及SharedPreferences读写、Adapter调用、页面刷新等逻辑,在子线程执行会直接抛出线程异常,所以看起来像对应方法没有被调用 - 间隔参数配置错误:当前定义的
notify_interval是5分钟(1000*60*5),不是需求要求的10分钟 - 定时器没有销毁逻辑:服务停止时没有主动销毁Timer,会导致内存泄漏,甚至后台持续跑无效任务
修复后的实现方案
优化思路:仅在定位服务启动时初始化一次定时器,每次定位更新只缓存最新位置,定时器到点后取缓存的最新位置上传,不需要每次定位回调都创建定时器。
关键修改代码
- 调整变量定义
// 修改为10分钟间隔 long notify_interval = 1000 * 60 * 10; // 增加标记位避免重复初始化定时器 private boolean isTimerRunning = false;
- 调整
onStartTacking方法,服务启动时仅初始化一次定时器
在onStartTacking方法的try代码块末尾添加如下逻辑:
// 定位启动时初始化一次定时器即可 if (!isTimerRunning && Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY, false)) { mTimer = new Timer(); mTimer.schedule(new TimerTaskToGetLocation(), 0, notify_interval); isTimerRunning = true; }
- 简化
onLocationChanged逻辑,仅保留位置缓存
@Override public void onLocationChanged(Location location) { Log.d("okh ", "onLocationChanged: "+System.currentTimeMillis()); if (location != null) { Log.d(TAG, String.valueOf(location.getAccuracy())); if (!AUtils.isNullString(String.valueOf(location.getLatitude())) && !AUtils.isNullString(String.valueOf(location.getLongitude()))) { // 只更新缓存的最新位置 Prefs.putString(AUtils.LAT, String.valueOf(location.getLatitude())); Prefs.putString(AUtils.LONG, String.valueOf(location.getLongitude())); } } else { Log.d(TAG, "onLocationChanged: no location found !!"); } }
- 修改
TimerTaskToGetLocation,切换到主线程执行上传逻辑
private class TimerTaskToGetLocation extends TimerTask { @Override public void run() { // 切到主线程执行,避免子线程操作系统组件、UI抛出异常 mHandler.post(() -> { if (Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY, false)) { sendLocation(); } }); } }
- 修改
onStopTracking方法,服务停止时销毁定时器
public void onStopTracking(Context context) { mAdapter.shareLocation(); LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); locationManager.removeUpdates(this); // 销毁定时器避免内存泄漏 if (mTimer != null) { mTimer.cancel(); mTimer = null; isTimerRunning = false; } }
额外优化建议
如果你的应用需要后台稳定运行定时上传,建议用AlarmManager或者WorkManager替代Timer,Timer在APP切后台、系统休眠时会被系统挂起,定时准确率无法保障。
内容的提问来源于stack exchange,提问作者gopssays
相关产品推荐
相关产品推荐

