我正在尝试在 Flutter 应用程序中托管来自 ArcGIS Maps SDK for Kotlin v200.1 的本机 MapView。
这是我的
main.dart
文件,它仅在支架内显示自定义 MapView
小部件:
// lib/main.dart
import 'package:flutter/material.dart';
import 'map_view.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('ArcGIS Map View'),
),
body: const Center(
child: MapView()
),
),
);
}
}
MapView
小部件看起来像这样:
// lib/map_view.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class MapView extends StatelessWidget {
const MapView({super.key});
@override
Widget build(BuildContext context) {
if (defaultTargetPlatform == TargetPlatform.iOS) {
return const UiKitView(viewType: _viewType);
} else if (defaultTargetPlatform == TargetPlatform.android) {
return const AndroidView(viewType: _viewType);
} else {
throw UnsupportedError('Platform not supported');
}
}
static const _viewType = 'mapView';
}
在 Android 端,我尝试创建 ArcGIS 地图视图作为
PlatformView
: 的一部分
// android/app/src/main/kotlin/com/example/test/NativeView.kt
package com.example.test
import android.content.Context
import android.view.View
import io.flutter.plugin.platform.PlatformView
import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.BasemapStyle
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.mapping.view.MapView
internal class NativeView(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView {
private val mapView: MapView
init {
ArcGISEnvironment.apiKey = ApiKey.create("<hidden>")
mapView = MapView(context)
mapView.map = ArcGISMap(BasemapStyle.ArcGISTopographic)
mapView.setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0))
}
override fun getView(): View {
return mapView
}
override fun dispose() {}
}
NativeView
由 NativeViewFactory
实例化,如 Flutter 文档中所述(托管原生 Android 视图)。
在 Android 模拟器中运行 Flutter 应用程序时,它在启动时崩溃,并出现异常,提示“lateinit property lifeCycleOwner has not beinitialed”:
A Dart VM Service on sdk gphone64 x86 64 is available at: http://127.0.0.1:65061/zcoQFFeeeZk=/
The Flutter DevTools debugger and profiler on sdk gphone64 x86 64 is available at:
http://127.0.0.1:9102?uri=http://127.0.0.1:65061/zcoQFFeeeZk=/
I/PlatformViewsController(10555): Hosting view in view hierarchy for platform view: 0
I/Choreographer(10555): Skipped 62 frames! The application may be doing too much work on its main thread.
E/FrameEvents(10555): updateAcquireFence: Did not find frame.
W/Parcel (10555): Expecting binder but got null!
I/TextureView(10555): onSurfaceTextureAvailable
D/AndroidRuntime(10555): Shutting down VM
E/FrameEvents(10555): updateAcquireFence: Did not find frame.
E/AndroidRuntime(10555): FATAL EXCEPTION: main
E/AndroidRuntime(10555): Process: com.example.test, PID: 10555
E/AndroidRuntime(10555): kotlin.UninitializedPropertyAccessException: lateinit property lifeCycleOwner has not been initialized
E/AndroidRuntime(10555): at com.arcgismaps.mapping.view.GeoView.getLifeCycleOwner$api_release(GeoView.kt:110)
E/AndroidRuntime(10555): at com.arcgismaps.mapping.view.GeoView$RenderingThread.onSurfaceTextureAvailable(GeoView.kt:1630)
E/AndroidRuntime(10555): at android.view.TextureView.getTextureLayer(TextureView.java:466)
E/AndroidRuntime(10555): at android.view.TextureView.draw(TextureView.java:415)
E/AndroidRuntime(10555): at android.view.View.updateDisplayListIfDirty(View.java:22061)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:22925)
E/AndroidRuntime(10555): at android.view.ViewGroup.drawChild(ViewGroup.java:4529)
E/AndroidRuntime(10555): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4290)
E/AndroidRuntime(10555): at android.view.View.updateDisplayListIfDirty(View.java:22052)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:22925)
E/AndroidRuntime(10555): at android.view.ViewGroup.drawChild(ViewGroup.java:4529)
E/AndroidRuntime(10555): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4290)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:23197)
E/AndroidRuntime(10555): at io.flutter.plugin.platform.PlatformViewWrapper.draw(PlatformViewWrapper.java:305)
E/AndroidRuntime(10555): at android.view.View.updateDisplayListIfDirty(View.java:22061)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:22925)
E/AndroidRuntime(10555): at android.view.ViewGroup.drawChild(ViewGroup.java:4529)
E/AndroidRuntime(10555): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4290)
E/AndroidRuntime(10555): at android.view.View.updateDisplayListIfDirty(View.java:22052)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:22925)
E/AndroidRuntime(10555): at android.view.ViewGroup.drawChild(ViewGroup.java:4529)
E/AndroidRuntime(10555): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4290)
E/AndroidRuntime(10555): at android.view.View.updateDisplayListIfDirty(View.java:22052)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:22925)
E/AndroidRuntime(10555): at android.view.ViewGroup.drawChild(ViewGroup.java:4529)
E/AndroidRuntime(10555): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4290)
E/AndroidRuntime(10555): at android.view.View.updateDisplayListIfDirty(View.java:22052)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:22925)
E/AndroidRuntime(10555): at android.view.ViewGroup.drawChild(ViewGroup.java:4529)
E/AndroidRuntime(10555): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4290)
E/AndroidRuntime(10555): at android.view.View.draw(View.java:23197)
E/AndroidRuntime(10555): at com.android.internal.policy.DecorView.draw(DecorView.java:821)
E/AndroidRuntime(10555): at android.view.View.updateDisplayListIfDirty(View.java:22061)
E/AndroidRuntime(10555): at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:689)
E/AndroidRuntime(10555): at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:695)
E/AndroidRuntime(10555): at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:793)
E/AndroidRuntime(10555): at android.view.ViewRootImpl.draw(ViewRootImpl.java:4670)
E/AndroidRuntime(10555): at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4381)
E/AndroidRuntime(10555): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3600)
E/AndroidRuntime(10555): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2328)
E/AndroidRuntime(10555): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9087)
E/AndroidRuntime(10555): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1231)
E/AndroidRuntime(10555): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
E/AndroidRuntime(10555): at android.view.Choreographer.doCallbacks(Choreographer.java:899)
E/AndroidRuntime(10555): at android.view.Choreographer.doFrame(Choreographer.java:832)
E/AndroidRuntime(10555): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
E/AndroidRuntime(10555): at android.os.Handler.handleCallback(Handler.java:942)
E/AndroidRuntime(10555): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(10555): at android.os.Looper.loopOnce(Looper.java:201)
E/AndroidRuntime(10555): at android.os.Looper.loop(Looper.java:288)
E/AndroidRuntime(10555): at android.app.ActivityThread.main(ActivityThread.java:7872)
E/AndroidRuntime(10555): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(10555): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
E/AndroidRuntime(10555): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
D/TrafficStats(10555): tagSocket(123) with statsTag=0xffffffff, statsUid=-1
I/Process (10555): Sending signal. PID: 10555 SIG: 9
Lost connection to device.
当使用旧版 ArcGIS Runtime SDK for Android v100.15.2 时,它将按预期工作:
// android/app/src/main/kotlin/com/example/test/NativeView.kt
package com.example.test
import android.content.Context
import android.view.View
import io.flutter.plugin.platform.PlatformView
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.view.MapView
import com.esri.arcgisruntime.mapping.BasemapStyle
import com.esri.arcgisruntime.mapping.Viewpoint
internal class NativeView(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView {
private val mapView: MapView
init {
ArcGISRuntimeEnvironment.setApiKey("<hidden>")
mapView = MapView(context)
mapView.map = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC)
mapView.setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0))
}
override fun getView(): View {
return mapView
}
override fun dispose() {}
}
启动后,我可以看到正在显示的地图视图:
我不是一名经验丰富的 Android 开发人员。有谁知道 v200.1 方法有什么问题吗?
版本信息:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.10.6, on macOS 13.4.1 22F770820d darwin-x64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] VS Code (version 1.80.1)
[✓] VS Code (version 1.81.0-insider)
[✓] Connected device (3 available)
[✓] Network resources
• No issues found!
编辑:有人尝试使用 React Native 做完全相同的事情,并在启动时得到相同的运行时异常(StackOverflow post)。然而不幸的是,没有人回复该帖子。
Arcgis SDK 版本 200.15.2 要求您的 Activity 扩展 AppCompatActivity() 并让生命周期观察您的地图视图
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(mapView) // <= you need this
}
我在使用Arcgis和Platformview时遇到了和你同样的问题,并提出了两种方法:
PlatformView
和AppCompatActivity()
-> 我还没有测试过这个方法internal class NativeView(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView, AppCompatActivity() {
private val mapView: MapView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(mapView) // <= you need this
}
AppCompatActivity()
的 Activity 并使用 Flutter 中的 invokeMethodChannel 来打开该 Activity -> 这对我有用