github上有一个百度地图的实现 xx_fluttify,他不只有百度地图,还有各种地图的实现,后来改收费了,高德的key没申请下来,我就下载了百度的lib。
用地图没大问题,就是速度不咋地,platformview的原因。当我需要geo反查时出现问题了,这个库一直有回调,即使我已经把当前的widget关了,各种dispose,依然会有查询结果回调,这显然是内存泄露了。
基于速度与内存的考虑,地图定位选址功能就不用它了。
毕竟写一个拖动地图选址还是不难地。而且native的view速度快多了。
遇到了一个麻烦,写一个plugin,但是要启动activity,然后选完以后onresult返回,插件里怎么启动,怎么返回呢?
查了下其它插件,里面有一个可以获取activity的。
class BaiduMapPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware 插件类
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) 这个方法会走
public static void registerWith(Registrar registrar) {}这个旧方法不会走了。但也做一些适配
先声明private Activity activity;
public static void registerWith(Registrar registrar) {
System.out.println("registerWith:");
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.archko.map/baidu_map");
BaiduMapPlugin baiduMapPlugin = new BaiduMapPlugin();
baiduMapPlugin.activity = registrar.activity();
channel.setMethodCallHandler(baiduMapPlugin);
}
得到了activity了。
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
System.out.println("onMethodCall:" + call.method);
if (call.method.equals("getLocation")) {
if (null != activity) {
resultMap.put(String.valueOf(REQUEST_GPS), result);
Intent intent = new Intent(activity, AreaSelectorWithMapActivity.class);
activity.startActivityForResult(intent, REQUEST_GPS);
}
} else {
result.notImplemented();
}
}
当传过来的方法是这个的时候,启动它。
resultMap.put(String.valueOf(REQUEST_GPS), result);
这个是将返回指针保留下来。便于在返回的时候用。
当前类不是activity,只是一个plugin,怎么接收呢?
@Override
public void onAttachedToActivity(ActivityPluginBinding binding) {
binding.addActivityResultListener(new PluginRegistry.ActivityResultListener() {
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_GPS) {
Result result = resultMap.get(String.valueOf(REQUEST_GPS));
if (resultCode == Activity.RESULT_OK) {
String location = data.getExtras().getString("location");
Log.d(TAG, "data:" + location);
if (null != result) {
Map map = new HashMap();
map.put("code", 0);
map.put("data", location);
result.success(map);
}
} else {
if (null != result) {
Map map = new HashMap();
map.put("code", -1);
result.error("error", "error", map);
}
}
resultMap.remove(String.valueOf(REQUEST_GPS));
}
return false;
}
});
activity = binding.getActivity();
}
这个方法覆盖了,就可以接收到了。
剩下的就是选址了。
地图什么时候初始化呢?假如你主工程有初始化,这里就不用了,假如没有,在定位Activity里onCreate()方法中调用:
SDKInit.init(getApplicationContext());
public class SDKInit {
public static boolean hasInit = false;
public static void init(Context context) {
if (!hasInit) {
SDKInitializer.initialize(context);
hasInit = true;
}
}
}
核心点就是,地图上盖一个指针,然后监听地图的移动,结束后,拿到中间这个位置,去反查位置。
mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
}
@Override
public void onMapStatusChange(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
}
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
//移动地图中心的时候会产生循环调用
if (!requestMoveCenter) {
if (mapStatus != null && mapStatus.bound != null) {
upDateMapLocation(mapStatus.bound.getCenter().latitude, mapStatus.bound.getCenter().longitude);
}
}
}
});
这里估计就是之前的库死循环一直调用的问题所在了。但作者说,后面的要收费,所以改不了。
LatLng point = new LatLng(latitude, longitude);
mSearch.reverseGeoCode(mReverseGeoCodeOption.location(point));
查完,更新一下中心点的marker,
private void updateBaiduMapCenterTip(String tip, LatLng latLng) {
if (null == mBaiduMap || TextUtils.isEmpty(tip) || null == latLng) {
return;
}
try {
map_address.setText(String.format("选中的位置:%s", tip));
mBaiduMap.clear();
if (requestMoveCenter) {
//移动地图中心点
mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(latLng));
requestMoveCenter = false;
}
//百度地图提示TextView
TextView mTipText = new TextView(getApplicationContext());
mTipText.setBackgroundResource(R.drawable.bg_map_tip);
mTipText.setText(tip);
// 覆盖物(#addMapMarker)
mBaiduMap.showInfoWindow(new InfoWindow(mTipText, latLng, -47));
} catch (NullPointerException e) {
}
}
显示好看点。
选完之后,返回数据:
btn_save.setOnClickListener(v -> {
if (null == geoCodeResult) {
Toast.makeText(AreaSelectorWithMapActivity.this, "请移动地图选址", Toast.LENGTH_LONG).show();
} else {
Intent intent = new Intent();
JSONObject jo = new JSONObject();
try {
jo.put("address", geoCodeResult.getAddress());
jo.put("lat", geoCodeResult.getLocation().latitude);
jo.put("lng", geoCodeResult.getLocation().longitude);
} catch (JSONException e) {
e.printStackTrace();
}
intent.putExtra("location", jo.toString());
setResult(RESULT_OK, intent);
finish();
}
});
这样,在插件中注册的监听器就可以得到了。
dart方面的调用:
class BaiduMap {
static const MethodChannel _channel =
const MethodChannel('com.archko.map/baidu_map');
static Future invokeMethod(String method, [dynamic arguments]) async {
return await _channel.invokeMethod(method, arguments);
}
static Future> invokeListMethod(String method,
[dynamic arguments]) async {
return await _channel.invokeListMethod(method, arguments);
}
static Future
https://github.com/archko/flutter_baidu_map.git 源码下载。