阿克苏建设网站,开江建设局网站,wordpress 缓存,做网站宣传语参考
【Flutter 混合开发】嵌入原生View-Android
默认使用Android studio 和 Kotlin
基本配置
创建flutter项目
在终端执行
flutter create batterylevel添加 Android 平台的实现
打开项目下的android/app/src/main/kotlin 下的 MainActivity.kt 文件。 我这里编辑器有…参考
【Flutter 混合开发】嵌入原生View-Android
默认使用Android studio 和 Kotlin
基本配置
创建flutter项目
在终端执行
flutter create batterylevel添加 Android 平台的实现
打开项目下的android/app/src/main/kotlin 下的 MainActivity.kt 文件。 我这里编辑器有提示最好使用其推荐这样代码会有提示 使用推荐后会新打开一个窗口在原窗口里提示的错误也将不会再提示
MainActivity.kt
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngineclass MainActivity : FlutterActivity() {// 在flutter引擎启动时将自定义的插件添加到flutter 引擎的插件列表中override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)flutterEngine.plugins.add(MyPlugin())}
}在项目文件下创建MyFlutterView.kt、MyFlutterViewFactory.kt、MyPlugin.kt 三个文件
MyFlutterView.kt编写的是原生安卓代码MyFlutterViewFactory.kt一个自定义的Flutter平台视图工厂用于创建创建Flutter平台视图并将其返回MyPlugin.kt 创建一个自定义的Flutter插件将自定义的Flutter平台视图工厂注册到Flutter引擎中以便在Flutter应用中使用该自定义视图。
MyFlutterView.kt
import android.content.Context
import android.view.View
import android.widget.TextView
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.platform.PlatformView// context 上下文对象
// messenger 用于消息传递BinaryMessenger二进制消息
// viewId View 生成时会分配一个唯一 ID
// args Flutter 传递的初始化参数
class MyFlutterView(context: Context,messenger: BinaryMessenger,viewId: Int,args: MapString, Any?
) :PlatformView {// PlatformView代表一个平台视图它是Flutter和原生平台之间的桥梁。// PlatformView允许在Flutter应用中嵌入原生视图并提供了与Flutter框架进行交互的方法。// 定义一个文本视图private val textView: TextView TextView(context)init {// 初始化文本视图textView.text 我是Android View}// 获取文本视图override fun getView(): View {return textView}// 销毁override fun dispose() {}
}MyFlutterViewFactory.kt
import android.content.Context
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory// 用于注册PlatformView
class MyFlutterViewFactory(private val messenger: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE
) {// 创建PlatformViewoverride fun create(context: Context, viewId: Int, args: Any?): PlatformView {return MyFlutterView(context, messenger, viewId, args as MapString, Any?)}}MyPlugin.kt com.example.batterylevel/custom_platform_view 是自定义平台视图的标识符需要保证唯一。 标识符通常由小写字母、数字和斜杠/组成并且不包含空格或特殊字符。 具体如何编写没查到参考文章应该是 按着包名/视图的描述的格式感觉挺好的
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.PluginRegistryclass MyPlugin : FlutterPlugin {// onAttachedToEngine 在Flutter插件与Flutter引擎绑定时被调用。// 在这个方法中可以执行一些初始化操作例如注册平台视图工厂、注册方法调用处理器等override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {// 消息发送器val messenger: BinaryMessenger binding.binaryMessenger//binding.platformViewRegistry.registerViewFactory(com.example.batterylevel/custom_platform_view, MyFlutterViewFactory(messenger))}// 注册视图companion object {JvmStaticfun registerWith(registrar: PluginRegistry.Registrar) {registrar.platformViewRegistry().registerViewFactory(com.example.batterylevel/custom_platform_view,MyFlutterViewFactory(registrar.messenger()))}}// 用于在插件从 Flutter 引擎中分离时执行清理操作。// 当插件不再需要与 Flutter 引擎通信时例如应用关闭或插件被移除时onDetachedFromEngine 方法会被调用。override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {}
}基本内容编写完成后回到flutter项目的部分进行运行 main.dart
void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});// This widget is the root of your application.overrideWidget build(BuildContext context) {return MaterialApp(title: 嵌入原生View-Android,theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),useMaterial3: true,),home: const PlatformViewDemo(),);}
}class PlatformViewDemo extends StatelessWidget {const PlatformViewDemo({super.key});overrideWidget build(BuildContext context) {platformView() {// 如果是安卓平台则返回一个AndroidView对象// AndroidView 是 Flutter 提供的一个小部件用于在 Flutter 中嵌入原生 Android 视图if (defaultTargetPlatform TargetPlatform.android) {// 标识符要保持一致return const AndroidView(viewType: com.example.batterylevel/custom_platform_view,);}}return Scaffold(appBar: AppBar(),body: Center(child: platformView(),),);}
}flutter与原生之间的通信
关于通信可以看一下这篇文章Flutter与原生如何进行通信
简单的参数传递
flutter中的修改main.dart
class PlatformViewDemoState extends StatePlatformViewDemo {overrideWidget build(BuildContext context) {platformView() {// 如果是安卓平台则返回一个AndroidView对象// AndroidView 是 Flutter 提供的一个小部件用于在 Flutter 中嵌入原生 Android 视图if (defaultTargetPlatform TargetPlatform.android) {// 标识符要保持一致return const AndroidView(viewType: com.example.batterylevel/custom_platform_view,creationParams: {text: AndroidTextView122},creationParamsCodec: StandardMessageCodec(),);}}return Scaffold(appBar: AppBar(),body: Center(child: platformView(),),);}
}creationParams 传递的参数插件可以将此参数传递给 AndroidView 的构造函数。creationParamsCodec 将 creationParams 编码后再发送给平台侧它应该与传递给构造函数的编解码器匹配。值的范围 StandardMessageCodec这是 Flutter 默认的编解码器用于序列化和反序列化标准数据类型例如字符串、数字、布尔值、列表和映射JSONMessageCodec使用 JSON 格式进行序列化和反序列化。它可以用于传递复杂的数据结构例如嵌套的映射和列表。StringCodec用于将字符串编码为字节流并在需要时进行解码。它适用于只传递字符串类型的创建参数。BinaryCodec用于直接传递字节流类型的创建参数不进行额外的编码或解码
修改 MyFlutterView.kt
class MyFlutterView(context: Context,messenger: BinaryMessenger,viewId: Int,args: MapString, Any?
) :PlatformView {// PlatformView代表一个平台视图它是Flutter和原生平台之间的桥梁。// PlatformView允许在Flutter应用中嵌入原生视图并提供了与Flutter框架进行交互的方法。// 定义一个文本视图private val textView: TextView TextView(context)init {// 初始化文本视图// 没学过Kotlin大体意思是参数存在则赋值args?.also { map -println(map[text])println(参数)textView.text map[text] as String}}// 获取文本视图override fun getView(): View {return textView}// 销毁override fun dispose() {}
}使用MethodChannel 通信
main.dart
class PlatformViewDemoState extends StatePlatformViewDemo {// 用于通信的通道static const platform MethodChannel(com.flutter.guide.MyFlutterView);overrideWidget build(BuildContext context) {platformView() {// 如果是安卓平台则返回一个AndroidView对象// AndroidView 是 Flutter 提供的一个小部件用于在 Flutter 中嵌入原生 Android 视图if (defaultTargetPlatform TargetPlatform.android) {// 标识符要保持一致return const AndroidView(viewType: com.example.batterylevel/custom_platform_view,creationParams: {text: 向安卓传参数},creationParamsCodec: StandardMessageCodec(),);}}return Scaffold(appBar: AppBar(),body: Column(children: [ElevatedButton(onPressed: () {// invokeMethod 的作用是在特定的上下文中调用指定的方法。它接受两个参数方法名称和一个包含参数的对象platform.invokeMethod(setText, {name: 张三, age: 18});},child: const Text(使用MethodChannel通信)),Expanded(child: platformView()!)],));}
}修改 MyFlutterView.kt
class MyFlutterView(context: Context,messenger: BinaryMessenger,viewId: Int,args: MapString, Any?
) :PlatformView, MethodChannel.MethodCallHandler {// PlatformView代表一个平台视图它是Flutter和原生平台之间的桥梁。// PlatformView允许在Flutter应用中嵌入原生视图并提供了与Flutter框架进行交互的方法。// 定义一个文本视图private val textView: TextView TextView(context)private var methodChannel: MethodChannelinit {// 初始化文本视图// 没学过Kotlin大体意思是参数存在则赋值args?.also { map -textView.text map[text] as String}// com.flutter.guide.MyFlutterView 标识保证唯一与flutter中的保持一致methodChannel MethodChannel(messenger, com.flutter.guide.MyFlutterView)methodChannel.setMethodCallHandler(this)}// 获取文本视图override fun getView(): View {return textView}// 销毁override fun dispose() {methodChannel.setMethodCallHandler(null)}// 方法调用处理器override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {if (call.method setText) {val name call.argument(name) as String?val age call.argument(age) as Int?textView.text hello,$name,年龄$age} else {result.notImplemented()}}
}注
methodChannel MethodChannel(messenger, com.flutter.guide.MyFlutterView)
methodChannel.setMethodCallHandler(this)必须放在 args?.also { map -textView.text map[text] as String}后面好像存在执行顺序的问题。如果放在前面 textView.text map[text] as String不会执行
flutter接收来自原生的消息 在flutter中使用invokeMethod调用原生的方法。在原生中处理对应方法时如果要向flutter中返回消息可以使用
textView.text hello,$name,年龄$age
result.success(收到了来自flutter的调用)在flutter中正常接收即可
ElevatedButton(onPressed: () async{// invokeMethod 的作用是在特定的上下文中调用指定的方法。它接受两个参数方法名称和一个包含参数的对象var res await platform.invokeMethod(setText, {name: 张三, age: 18});print(res);},child: const Text(使用MethodChannel通信))解决多个原生View通信冲突问题
这个看原文章就好了主要是保证每一个通道都是唯一的。
原生 View 生成时系统会为其生成唯一idviewId使用 viewId 构建不同名称的 MethodChannel。
class MyFlutterView(context: Context, messenger: BinaryMessenger, viewId: Int, args: MapString, Any?) : PlatformView, MethodChannel.MethodCallHandler {val textView: TextView TextView(context)private var methodChannel: MethodChannelinit {args?.also {textView.text it[text] as String}methodChannel MethodChannel(messenger, com.flutter.guide.MyFlutterView_$viewId)methodChannel.setMethodCallHandler(this)}...
}Flutter 端为每一个原生 View 创建不同的MethodChannel
var platforms [];AndroidView(viewType: plugins.flutter.io/custom_platform_view,onPlatformViewCreated: (viewId) {print(viewId:$viewId);platforms.add(MethodChannel(com.flutter.guide.MyFlutterView_$viewId));},creationParams: {text: Flutter传给AndroidTextView的参数},creationParamsCodec: StandardMessageCodec(),
)给第一个发送消息
platforms[0].invokeMethod(setText, {name: laomeng, age: 18});