尝试封装高德地图定位的一些疑问
查看高德定位Demo,分析后主要有几步
配置参数->开始定位->关闭定位->onDestory()释放资源
设计思路:
低侵入性--其他module不会耦合到定位SDK的代码
傻瓜式使用--结合lifecycle监听页面自动释放资源,用户调用方法处理回调即可
相关代码:
internal class AppLocationHelper {
private var locationClient: AMapLocationClient? = null
private var locationOption: AMapLocationClientOption? = null
private var appLocationListener: IAppLocationListener? = null
/**
* 开始定位
*/
fun startLocation(activity: FragmentActivity, iAppLocationListener: IAppLocationListener?) {
this.appLocationListener = iAppLocationListener
activity.lifecycle.addObserver(AppLifecycleObserver())
//初始化client
locationClient = AMapLocationClient(activity.applicationContext)
locationOption = getDefaultOption()
locationClient?.apply {
//设置定位参数
setLocationOption(locationOption)
// 设置定位监听
setLocationListener(locationListener)
// 启动定位
startLocation()
}
}
private fun destroyLocation() {
if (null != locationClient) {
/**
* 如果AMapLocationClient是在当前Activity实例化的,
* 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
*
* 由于我们设计成一次性定位,因此停止定位同时释放资源
*/
locationClient?.stopLocation()
locationClient?.onDestroy()
locationClient = null
locationOption = null
}
}
/**
* 默认的定位参数
*
*/
private fun getDefaultOption(): AMapLocationClientOption {
//....
return mOption
}
private val locationListener = AMapLocationListener { location ->
//a!=null和null!=a 效果一样,但后者可以避免一些赋值异常,equal类似,把常量放在前面
if (null != appLocationListener && null != location) {
appLocationListener?.onLocationChanged(toJsonObject(location))
}
}
/*
错误码errorCode说明
具体看R.string.amapErrorCodeInfo
*/
private fun toJsonObject(location: AMapLocation): JSONObject {
val jsonObject = JSONObject()
jsonObject.put("latitude", location.latitude)
jsonObject.put("longitude", location.longitude)
jsonObject.put("province", location.province)
jsonObject.put("coordType", location.coordType)
jsonObject.put("city", location.city)
jsonObject.put("district", location.district)
jsonObject.put("cityCode", location.cityCode)
jsonObject.put("adCode", location.adCode)
jsonObject.put("address", location.address)
jsonObject.put("country", location.country)
jsonObject.put("poiName", location.poiName)
jsonObject.put("street", location.street)
jsonObject.put("streetNum", location.streetNum)
jsonObject.put("aoiName", location.aoiName)
jsonObject.put("floor", location.floor)
jsonObject.put("errorCode", location.errorCode)
jsonObject.put("errorInfo", location.errorInfo)
jsonObject.put("locationDetail", location.locationDetail)
jsonObject.put("description", location.description)
jsonObject.put("locationType", location.locationType)
jsonObject.put("conScenario", location.conScenario)
return jsonObject
}
/**
* LifecycleObserver监听当前承载的Activity的生命周期
*/
inner class AppLifecycleObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
destroyLocation()
}
}
}
疑问一:
var locationClient=AMapLocationClient(activity.applicationContext)持有content,如果 AppLocationHelper 定义成 object类, locationClient会警告内存泄漏,这个该怎么优化,没找到方案
疑问二:
startLocation(activity: FragmentActivity) 这样封装的传参,一般用哪个比较合适,Activity/FragmentActivity/ComponentActivity,这几个都能用,有点纠结
正在回答 回答被采纳积分+1
对于定位相关的功能逻辑通常会将AppLocationHelper职能的类设计成单例,为了防止AMapLocationClient中的context内存泄漏问题,建议获取应用的application的context;
对于开始定位这个功能主要关注点是:
定位成功;
定位失败
所以,建议startLocation方法的入参定义为一个包含定位成功和定位失败两个方法的接口,这样也能和activity解耦。
注意,这种情况下单例不要用object,因为此种形式的单例会被编译成:
public final class AppLocationHelper { private static AMapLocationClient locationClient; private static AMapLocationClientOption locationOption; public static final AppLocationHelper INSTANCE; private AppLocationHelper() { } static { AppLocationHelper var0 = new AppLocationHelper(); INSTANCE = var0; } }
locationClient被修饰成静态变量,AS的静态代码估计也是基于这个识别的,可以用课程中讲的静态内部类式的单例来实现。
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星