You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在定时器中调用LocationListener内置方法 实现间隔10分钟上传位置

问题根因分析
  • 重复创建Timer实例:原代码在每次onLocationChanged触发时都会新建Timer对象,会导致大量重复定时任务并行执行,完全不符合间隔10分钟上传一次的需求
  • Timer运行在子线程:TimerTask的run()方法执行在工作线程,sendLocation()方法涉及SharedPreferences读写、Adapter调用、页面刷新等逻辑,在子线程执行会直接抛出线程异常,所以看起来像对应方法没有被调用
  • 间隔参数配置错误:当前定义的notify_interval是5分钟(1000*60*5),不是需求要求的10分钟
  • 定时器没有销毁逻辑:服务停止时没有主动销毁Timer,会导致内存泄漏,甚至后台持续跑无效任务
修复后的实现方案

优化思路:仅在定位服务启动时初始化一次定时器,每次定位更新只缓存最新位置,定时器到点后取缓存的最新位置上传,不需要每次定位回调都创建定时器。

关键修改代码

  1. 调整变量定义
// 修改为10分钟间隔
long notify_interval = 1000 * 60 * 10;
// 增加标记位避免重复初始化定时器
private boolean isTimerRunning = false;
  1. 调整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;
}
  1. 简化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 !!");
    }
}
  1. 修改TimerTaskToGetLocation,切换到主线程执行上传逻辑
private class TimerTaskToGetLocation extends TimerTask {
    @Override
    public void run() {
        // 切到主线程执行,避免子线程操作系统组件、UI抛出异常
        mHandler.post(() -> {
            if (Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY, false)) {
                sendLocation();
            }
        });
    }
}
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:06:04