企业门户网站模式,wordpress判断,深圳有名的设计公司,wordpress主题音乐背景
本文的背景#xff0c;是因为我在开发高德地图时#xff0c;需要自定义高德比例尺位置和样式#xff1b;但结果查看了AMap Flutter插件和AMap SDK源码后#xff0c;发现AMap无法添加自定义MyMethodCallHandler的实现类#xff01;
why#xff1f;
源码
在Flutte…背景
本文的背景是因为我在开发高德地图时需要自定义高德比例尺位置和样式但结果查看了AMap Flutter插件和AMap SDK源码后发现AMap无法添加自定义MyMethodCallHandler的实现类
why
源码
在Flutter中高德地图的每个地图视图都是通过AMapPlatformView类生成且管理的源码如下
package com.amap.flutter.map;import android.content.Context;
import android.os.Bundle;
import android.view.View;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.TextureMapView;
import com.amap.flutter.map.core.MapController;
import com.amap.flutter.map.overlays.marker.MarkersController;
import com.amap.flutter.map.overlays.polygon.PolygonsController;
import com.amap.flutter.map.overlays.polyline.PolylinesController;
import com.amap.flutter.map.utils.LogUtil;import java.util.HashMap;
import java.util.Map;import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView;/*** author whm* date 2020/10/27 5:49 PM* mail hongming.whmalibaba-inc.com* since*/
public class AMapPlatformViewimplementsDefaultLifecycleObserver,ActivityPluginBinding.OnSaveInstanceStateListener,MethodChannel.MethodCallHandler,PlatformView {private static final String CLASS_NAME AMapPlatformView;private final MethodChannel methodChannel;private MapController mapController;private MarkersController markersController;private PolylinesController polylinesController;private PolygonsController polygonsController;private TextureMapView mapView;private boolean disposed false;private final MapString, MyMethodCallHandler myMethodCallHandlerMap;AMapPlatformView(int id,Context context,BinaryMessenger binaryMessenger,LifecycleProvider lifecycleProvider,AMapOptions options) {methodChannel new MethodChannel(binaryMessenger, amap_flutter_map_ id);methodChannel.setMethodCallHandler(this);myMethodCallHandlerMap new HashMapString, MyMethodCallHandler(8);try {mapView new TextureMapView(context, options);AMap amap mapView.getMap();mapController new MapController(methodChannel, mapView);markersController new MarkersController(methodChannel, amap);polylinesController new PolylinesController(methodChannel, amap);polygonsController new PolygonsController(methodChannel, amap);initMyMethodCallHandlerMap();lifecycleProvider.getLifecycle().addObserver(this);} catch (Throwable e) {LogUtil.e(CLASS_NAME, init, e);}}private void initMyMethodCallHandlerMap() {String[] methodIdArray mapController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, mapController);}}methodIdArray markersController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, markersController);}}methodIdArray polylinesController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, polylinesController);}}methodIdArray polygonsController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, polygonsController);}}}public MapController getMapController() {return mapController;}public MarkersController getMarkersController() {return markersController;}public PolylinesController getPolylinesController() {return polylinesController;}public PolygonsController getPolygonsController() {return polygonsController;}Overridepublic void onMethodCall(NonNull MethodCall call, NonNull MethodChannel.Result result) {LogUtil.i(CLASS_NAME, onMethodCall call.method , arguments call.arguments);String methodId call.method;if (myMethodCallHandlerMap.containsKey(methodId)) {myMethodCallHandlerMap.get(methodId).doMethodCall(call, result);} else {LogUtil.w(CLASS_NAME, onMethodCall, the methodId: call.method , not implemented);result.notImplemented();}}Overridepublic void onCreate(NonNull LifecycleOwner owner) {LogUtil.i(CLASS_NAME, onCreate);try {if (disposed) {return;}if (null ! mapView) {mapView.onCreate(null);}} catch (Throwable e) {LogUtil.e(CLASS_NAME, onCreate, e);}}Overridepublic void onStart(NonNull LifecycleOwner owner) {LogUtil.i(CLASS_NAME, onStart);}Overridepublic void onResume(NonNull LifecycleOwner owner) {LogUtil.i(CLASS_NAME, onResume);try {if (disposed) {return;}if (null ! mapView) {mapView.onResume();}} catch (Throwable e) {LogUtil.e(CLASS_NAME, onResume, e);}}Overridepublic void onPause(NonNull LifecycleOwner owner) {LogUtil.i(CLASS_NAME, onPause);try {if (disposed) {return;}mapView.onPause();} catch (Throwable e) {LogUtil.e(CLASS_NAME, onPause, e);}}Overridepublic void onStop(NonNull LifecycleOwner owner) {LogUtil.i(CLASS_NAME, onStop);}Overridepublic void onDestroy(NonNull LifecycleOwner owner) {LogUtil.i(CLASS_NAME, onDestroy);try {if (disposed) {return;}destroyMapViewIfNecessary();} catch (Throwable e) {LogUtil.e(CLASS_NAME, onDestroy, e);}}Overridepublic void onSaveInstanceState(NonNull Bundle bundle) {LogUtil.i(CLASS_NAME, onDestroy);try {if (disposed) {return;}mapView.onSaveInstanceState(bundle);} catch (Throwable e) {LogUtil.e(CLASS_NAME, onSaveInstanceState, e);}}Overridepublic void onRestoreInstanceState(Nullable Bundle bundle) {LogUtil.i(CLASS_NAME, onDestroy);try {if (disposed) {return;}mapView.onCreate(bundle);} catch (Throwable e) {LogUtil.e(CLASS_NAME, onRestoreInstanceState, e);}}Overridepublic View getView() {LogUtil.i(CLASS_NAME, getView);return mapView;}Overridepublic void dispose() {LogUtil.i(CLASS_NAME, dispose);try {if (disposed) {return;}methodChannel.setMethodCallHandler(null);destroyMapViewIfNecessary();disposed true;} catch (Throwable e) {LogUtil.e(CLASS_NAME, dispose, e);}}private void destroyMapViewIfNecessary() {if (mapView null) {return;}mapView.onDestroy();}}
分析
通过上面的源码可以发现如下几点
在它onMethodCall回调方法中判断了方法名是否在myMethodCallHandlerMap中存在
Overridepublic void onMethodCall(NonNull MethodCall call, NonNull MethodChannel.Result result) {LogUtil.i(CLASS_NAME, onMethodCall call.method , arguments call.arguments);String methodId call.method;if (myMethodCallHandlerMap.containsKey(methodId)) {myMethodCallHandlerMap.get(methodId).doMethodCall(call, result);} else {LogUtil.w(CLASS_NAME, onMethodCall, the methodId: call.method , not implemented);result.notImplemented();}}myMethodCallHandlerMap 是一个final属性这也就意味着它在构造函数中已经实例化了且不能更改值只能修改内容它通过initMyMethodCallHandlerMap注册所有的Hnadler
private final MapString, MyMethodCallHandler myMethodCallHandlerMap;AMapPlatformView(int id,Context context,BinaryMessenger binaryMessenger,LifecycleProvider lifecycleProvider,AMapOptions options) {methodChannel new MethodChannel(binaryMessenger, amap_flutter_map_ id);methodChannel.setMethodCallHandler(this);myMethodCallHandlerMap new HashMapString, MyMethodCallHandler(8);try {mapView new TextureMapView(context, options);AMap amap mapView.getMap();mapController new MapController(methodChannel, mapView);markersController new MarkersController(methodChannel, amap);polylinesController new PolylinesController(methodChannel, amap);polygonsController new PolygonsController(methodChannel, amap);initMyMethodCallHandlerMap();lifecycleProvider.getLifecycle().addObserver(this);} catch (Throwable e) {LogUtil.e(CLASS_NAME, init, e);}
}通过initMyMethodCallHandlerMap方法可以看出它只注册了mapController、markersController、polylinesController、polygonsController四类Handler且没有提供可以自定义注册的方法所以我也无能为力了
private void initMyMethodCallHandlerMap() {String[] methodIdArray mapController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, mapController);}}methodIdArray markersController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, markersController);}}methodIdArray polylinesController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, polylinesController);}}methodIdArray polygonsController.getRegisterMethodIdArray();if (null ! methodIdArray methodIdArray.length 0) {for (String methodId : methodIdArray) {myMethodCallHandlerMap.put(methodId, polygonsController);}}}解决思路
1. 通过修改initMyMethodCallHandlerMap属性值不推荐
通过上面分析可以想到通过修改initMyMethodCallHandlerMap属性值自定义handler但前提时需要拿到对应的AMapPlatformView实例通常的方法可以通过ServiceLoader来获取但在Android中ServiceLoader是不用生效的Android环境中必须通过PathClassLoader、DexClassLoader来加载类具体加载方法可以参考其他大神的博客我这里不做过多追述因为我不推荐
2. 通过PlatformViewsController来获取视图推荐
推荐这个方法是因为它可以i通过mapId直接获取且不用过多介入到内存和进程中的交互中
创建一个自定义MethodChannel
var methodChannel MethodChannel(flutterEngine.dartExecutor.binaryMessenger, method_channel_id)methodChannel.setMethodCallHandler { call, result -run {//....}}AMapPlatformView继承PlatformView所以可以通过FlutterEngine.getPlatformViewsController().getPlatformViewById(viewId)方式获取获取到的是TextureMapView视图TextureMapView.getMap()可以获取AMap类从而实现对当前地图视图进行任何操作
class MainActivity : FlutterActivity() {var handerControllerMap HashMapString, IMyMethodCallHander();override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)IFlutterFactory.engineflutterEngine;}
}/*** 当前缩放级别下地图上1像素点对应的长度单位米。* param call* param result*/public void getScalePerPixel(MethodCall call, MethodChannel.Result result) {Object mapId call.argument(mapId);if (null call || null mapId) {return;}try {View view IFlutterFactory.engine.getPlatformViewsController().getPlatformViewById(Integer.parseInt(mapId.toString()));if (view ! null) {result.success(((TextureMapView) view).getMap().getScalePerPixel());} else {result.error(ScaleControllerExecption, 获取比例尺数据失败, );}} catch (Exception e) {result.error(ScaleControllerExecption, e.getMessage(), e.getLocalizedMessage());}}viewId 其实就是mapId可以通过AMapController.mapId获取而AMapController可以通过AMapWidget的onMapCreated的回调方法获取
void onMapCreated(AMapController controller) {//连接自定义的MethodChannelMethodChannel _channelMethodChannel(method_channel_id);//将mapId传给android端double? scaleawait _channel.invokeMethoddouble(scale#get,String,dynamic{mapId:_mapController.mapId});print(-----scale---$scale);
}