概述
Android百度地图定位多处回调调用问题
- 多处回调调用问题
- 改进
多处回调调用问题
为了方便使用,自己封装了一个百度地图定位工具。工具类没有使用单例模式,回调又用了一层handler来处理。每个activity都存在一个LocateUtil实例,本来想的是每个activity里定位工具都是独立的。但是实际运行时发现只要一处调用startLoaction,每个activity中的handler都会被调用。代码大概是这样的:
public class LocateUtil {
private LocationClient mLocationClient;
private BDLocationListener myListener;
private Handler mHandler;
public LocateUtil(Context context, Handler handler) {
mHandler = handler;
myListener = new MyLocationListener();
mLocationClient = new LocationClient(context.getApplicationContext());
}
public void initLocation(int span) {
initOption(span);
mLocationClient.registerLocationListener(myListener);
}
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
Message msg = new Message();
msg.what = xxx;
//封装自己要用的数据 locationModel
msg.obj = locationModel;
mHandler.sendMessage(msg);
}
}
public void startLocation() {
if (mLocationClient == null) {
return;
}
if (mLocationClient.isStarted()) {
mLocationClient.requestLocation();
} else {
mLocationClient.start();
}
}
public void closeLocation() {
if (mLocationClient != null) {
mLocationClient.stop();
mLocationClient.unRegisterLocationListener(myListener);
mLocationClient = null;
}
}
void initOption(int span) {
LocationClientOption option = new LocationClientOption();
//可选,默认gcj02,设置返回的定位结果坐标系
option.setCoorType("bd09ll");
//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的
option.setScanSpan(span);
//可选,设置是否需要地址信息,默认不需要
option.setIsNeedAddress(true);
//可选,默认false,设置是否使用gps
option.setOpenGps(true);
//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
option.setIsNeedLocationDescribe(true);
//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
option.setIsNeedLocationPoiList(true);
//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
option.setIgnoreKillProcess(false);
//可选,默认false,设置是否收集CRASH信息,默认收集
option.SetIgnoreCacheException(false);
mLocationClient.setLocOption(option);
}
}
查看了一下源码发现注册的回调是用一个list来存的(这源码看吐了,名字都是一些没有意义的字符,我改了改名字,稍微好看一点)
private ArrayList<BDLocationListener> listenerList = null;
private ArrayList<BDAbstractLocationListener> k = null;
...
private void e(Message msg) {
if (msg != null && msg.obj != null) {
BDLocationListener listener = (BDLocationListener)msg.obj;
if (this.listenerList == null) {
this.listenerList = new ArrayList();
}
if (!this.listenerList.contains(listener)) {
this.listenerList.add(listener);
}
}
}
启动最后调用这个函数应该是启动了一个service,然后把LocationClient通过Notification(这个应该百度自己封装了一个,找不到源码)和Intent传递过去,
/**
private void a(int var1, Notification var2) {
try {
Intent var3 = new Intent(this.f, f.class);
var3.putExtra("notification", var2);
var3.putExtra("id", var1);
var3.putExtra("command", 1);
if (VERSION.SDK_INT >= 26) {
this.f.startForegroundService(var3);
} else {
this.f.startService(var3);
}
this.H = true;
} catch (Exception var4) {
;
}
}
*/
LocationClient.a(this.a,
new com.baidu.location.a.bdNotification(LocationClient.i(this.a), LocationClient.j(this.a), this.a));
后面的源码实在看不懂了,我猜测LoactionClient用list来存回调函数在service中应该也会有个回调list,当得到定位结果的时候会遍历list的回调,所以会发生一处调用start多出调用回调的现象。
改进
后来我把注册回调放在的startLocation里,注销放在回调里,调用startLocation时才把回调注册到service里,用完直接注销,这样一个地方用其他地方就不会调回调了(没考虑线程同步,我做的项目里没有多处同时调用定位的地方)
public void startLocation() {
if (mLocationClient == null) {
return;
}
mLocationClient.registerLocationListener(myListener);
if (mLocationClient.isStarted()) {
mLocationClient.requestLocation();
} else {
mLocationClient.start();
}
}
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
Message msg = new Message();
...
mHandler.sendMessage(msg);
if(span == 0){
mLocationClient.unRegisterLocationListener(myListener);
}
}
}
其实应该不需要用handler,直接在页面写自己的BDLocationListener回调应该更直观。
最后
以上就是轻松板栗为你收集整理的Android百度地图定位多处回调调用问题多处回调调用问题改进的全部内容,希望文章能够帮你解决Android百度地图定位多处回调调用问题多处回调调用问题改进所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复