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

Android中如何用SharedPreference保存并替换LatLng位置以获取最新值?

Android使用SharedPreference保存并更新位置(LatLng)实现指南

没问题,这需求在Android开发里挺常见的,我给你一步步拆解实现思路和代码示例,保证清晰好懂:

1. 封装SharedPreference工具类

SharedPreference本身不能直接存储LatLng对象,我们需要把它转换成可存储的类型(比如拆分经纬度为浮点值,或者用Gson转成JSON字符串)。这里提供两种常用方案:

方案1:拆分经纬度存储(无需额外依赖)

这种方式简单直接,适合不需要复杂对象存储的场景:

class LocationPreferenceHelper(context: Context) {
    // 定义SharedPreference实例和存储键
    private val sharedPref = context.getSharedPreferences("LocationPrefs", Context.MODE_PRIVATE)
    private val KEY_LATITUDE = "saved_latitude"
    private val KEY_LONGITUDE = "saved_longitude"

    // 保存/更新位置(更新其实就是覆盖旧值,所以和保存逻辑一致)
    fun saveOrUpdateLocation(latLng: LatLng) {
        sharedPref.edit()
            .putFloat(KEY_LATITUDE, latLng.latitude.toFloat())
            .putFloat(KEY_LONGITUDE, latLng.longitude.toFloat())
            .apply() // 异步提交,避免阻塞主线程
    }

    // 获取最新保存的位置,返回null表示从未保存过
    fun getSavedLocation(): LatLng? {
        val savedLat = sharedPref.getFloat(KEY_LATITUDE, Float.MIN_VALUE)
        val savedLng = sharedPref.getFloat(KEY_LONGITUDE, Float.MIN_VALUE)
        
        return if (savedLat != Float.MIN_VALUE && savedLng != Float.MIN_VALUE) {
            LatLng(savedLat.toDouble(), savedLng.toDouble())
        } else {
            null
        }
    }
}

方案2:用Gson转JSON存储(适合复杂对象)

如果后续需要存储更多位置相关信息,用JSON序列化更灵活,需要先添加Gson依赖:

// 在app模块的build.gradle中添加
implementation 'com.google.code.gson:gson:2.10.1'

然后实现工具类:

class LocationPreferenceHelper(context: Context) {
    private val sharedPref = context.getSharedPreferences("LocationPrefs", Context.MODE_PRIVATE)
    private val KEY_LATLNG_JSON = "saved_latlng_json"
    private val gson = Gson()

    fun saveOrUpdateLocation(latLng: LatLng) {
        val latLngJson = gson.toJson(latLng)
        sharedPref.edit()
            .putString(KEY_LATLNG_JSON, latLngJson)
            .apply()
    }

    fun getSavedLocation(): LatLng? {
        val savedJson = sharedPref.getString(KEY_LATLNG_JSON, null)
        return savedJson?.let { gson.fromJson(it, LatLng::class.java) }
    }
}

2. 处理GPS位置更新并同步到SharedPreference

接下来需要在获取到新的GPS位置时,调用工具类的更新方法。这里推荐用Google的Fused Location Provider API(比原生LocationManager更稳定高效):

class MainActivity : AppCompatActivity() {
    private lateinit var locationPreferenceHelper: LocationPreferenceHelper
    private lateinit var fusedLocationClient: FusedLocationProviderClient
    private lateinit var locationCallback: LocationCallback

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 初始化工具类
        locationPreferenceHelper = LocationPreferenceHelper(this)
        // 初始化FusedLocationClient
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)

        // 配置位置请求参数
        val locationRequest = LocationRequest.create().apply {
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY // 高精度定位
            interval = 10000 // 10秒更新一次(根据需求调整)
            fastestInterval = 5000 // 最快更新间隔
        }

        // 定义位置回调,获取到新位置时更新SharedPreference
        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                super.onLocationResult(locationResult)
                locationResult.lastLocation?.let { location ->
                    val newLatLng = LatLng(location.latitude, location.longitude)
                    // 同步更新到SharedPreference
                    locationPreferenceHelper.saveOrUpdateLocation(newLatLng)
                    // 这里可以添加UI刷新等逻辑
                    Log.d("LocationUpdate", "新位置已保存:${newLatLng.latitude}, ${newLatLng.longitude}")
                }
            }
        }
    }

    override fun onStart() {
        super.onStart()
        // 检查定位权限,申请通过后开始请求位置更新
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {
            fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
        } else {
            // 动态申请定位权限
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1001)
        }
    }

    override fun onStop() {
        super.onStop()
        // 停止位置更新,避免后台耗电
        fusedLocationClient.removeLocationUpdates(locationCallback)
    }

    // 处理权限申请结果
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 1001 && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限通过后开始请求位置更新
            fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
        }
    }
}

3. 获取最新保存的位置

在任何需要的地方(比如启动APP时恢复位置),调用工具类的getSavedLocation()方法即可:

val savedLocation = locationPreferenceHelper.getSavedLocation()
savedLocation?.let {
    // 存在已保存的位置,做后续处理(比如显示地图标记)
    Log.d("SavedLocation", "最新保存的位置:${it.latitude}, ${it.longitude}")
} ?: run {
    // 没有保存过位置,提示用户或触发首次定位
    Log.d("SavedLocation", "未找到已保存的位置")
}

关键注意事项

  • 权限处理:务必在AndroidManifest.xml中添加定位权限,并动态申请:
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    
    Android 10及以上如果需要后台定位,还需添加ACCESS_BACKGROUND_LOCATION权限。
  • 空值判断:获取保存的位置时一定要判断是否为null,避免空指针异常。
  • 性能优化:根据业务需求调整位置更新的间隔,避免过于频繁的定位导致耗电过快。
  • 多进程场景:如果你的APP是多进程架构,MODE_PRIVATE的SharedPreference可能无法共享数据,建议改用ContentProvider或其他跨进程存储方案。

内容的提问来源于stack exchange,提问作者user9706969

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:18:08