美文网首页
Fiutter- 混合开发与原生Android交互

Fiutter- 混合开发与原生Android交互

作者: 盛世光阴 | 来源:发表于2021-11-29 10:44 被阅读0次

    前言

    FlutterGoogle开源的构建用户界面(UI)工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台。Flutter 开源、免费,拥有宽松的开源协议,适合商业项目。目前,Flutter已推出稳定的2.0版本。也是目前最火的跨平台开发工具之一

    header-illustration.png

    创建AndroidView

    Flutter中的Android项目使用AndroidStudio打开,然后在app的包名下新建一个View实现io.flutter.plugin.platform.PlatformView接口,使用PlatformView就可以将AndroidView嵌入到Flutter视图中去,由于需要进行视图对象创建所以在构造函数添加context

    • getView 返回你需要嵌入的AndroidView
    • dispose 调用此方法后,PlatformView 对象将不可用。调用此方法后,实现 PlatformView 的插件必须清除对 View对象和 PlatformView 的所有引用。 如果不这样做将导致内存泄漏。
    import android.content.Context
    import android.widget.TextView
    import io.flutter.plugin.platform.PlatformView
    
    class CustomerView(context: Context):PlatformView {
    
        val textView: TextView = TextView(context).apply {
            text = "Test View in Android "
        }
    
        override fun getView() = textView
    
        override fun dispose() {
    
        }
    }
    

    注册AndroidView

    新建一个类继承自PlatformViewFactory,在其中创建我们的View

    import android.content.Context
    import io.flutter.plugin.common.StandardMessageCodec
    import io.flutter.plugin.platform.PlatformView
    import io.flutter.plugin.platform.PlatformViewFactory
    
    class CustomerViewFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE){
    
        override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
            return CustomerView(context)
        }
    
    }
    

    新建一个类继承自FlutterPlugin

    import io.flutter.embedding.engine.plugins.FlutterPlugin
    
    class CustomerViewPlugin : FlutterPlugin {
    
        override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
            binding.platformViewRegistry.registerViewFactory("plugins.flutter.io/my_custom_platform_view",CustomerViewFactory())
        }
    
        override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    
        }
    
    }
    

    MainActivity中添加上述的Plugin,registerViewFactory中的viewTypeId参数是一个唯一标识字符串,后续将引用在flutter视图中

    import io.flutter.embedding.android.FlutterActivity
    import io.flutter.embedding.engine.FlutterEngine
    
    class MainActivity: FlutterActivity() {
    
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            flutterEngine.plugins.add(CustomerViewPlugin())
        }
    }
    

    Flutter中引用AndroidView

    class _MyHomePageState extends State<MyHomePage> {
      
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(widget.title),
          ),
          body: MyCustomerPlatformView(), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    class MyCustomerPlatformView extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        if (defaultTargetPlatform == TargetPlatform.android) {
          return AndroidView(viewType: ("plugins.flutter.io/my_custom_platform_view"));
        } else {
          return Text("No support this View");
        }
      }
    }
    
    搜狗截图20211102112139.png

    Flutter与原生之间相互交互

    上述案例中我们只是简单地额嵌入了一个原生View,这种只适用于一个静态页面的处理,如果需要页面之间动态交互,则需要添加一些额外的配置,交互无非就是你可以调用我的功能,我可以调用你的功能

    MethodChannel

    用于两端的相互调用,并且可以返回结果,Native调用Flutter时需要在主线程中进行

    Flutter发送数据/调用Native

    1. 在Flutter中创建MethodChannel
    var channel = MethodChannel("samples.flutter.dev/callNative");
    

    2.在Flutter中通过channel发送数据给到Native,通过invokeMethod函数发送到Native,然后当返回信息时将其进行显示

    Container(
            alignment: Alignment.center,
            child: GestureDetector(
              child: Text('Click to call Native'),
              onTap: () async {
                String result = await channel.invokeMethod("callNative", {"id": "1", "value": "Mike"});
                showDialog(context: context, builder: (context){
                  return AlertDialog(title: Text("提示"),content: Text(result));
                }
                );
              },
            ),
          )
    

    3.在Android中定义相关的接受,onMethodCall可以接受到此channel对应的调用,两端之间channel之间的关联是通过name,也就是这里给的samples.flutter.dev/NativeChannel,result.success()是本次调用反馈的结果

    class NativeMethodChannel(messenger: BinaryMessenger) : MethodChannel.MethodCallHandler {
    
        val channel = MethodChannel(messenger, "samples.flutter.dev/NativeChannel")
    
        init {
            channel.setMethodCallHandler(this)
        }
    
        override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
            if (call.method == "callNative") {
                val value = call.argument<String>("value")
                result.success("Received it: value is $value")
            }
        }
    }
    

    4.在NativeMainActivity中对NativeMethodChannel进行注册,这样它才会持续监听

        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            NativeMethodChannel(flutterEngine.dartExecutor.binaryMessenger)
        }
    
    channel.png

    Android发送数据/调用Flutter

    Android

                channel.invokeMethod("callFlutter","张三",object:MethodChannel.Result{
                    override fun success(result: Any?) {
                        Log.e("Mike","result $result")
                    }
    
                    override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
    
                    }
    
                    override fun notImplemented() {
    
                    }
    
                })
    

    Flutter端接收

      @override
      void initState() {
        super.initState();
        channel.setMethodCallHandler((call) {
            print("flutter called by native ${call.arguments}");
            return Future.value("res");
        });
      }
    

    BasicMessageChannel
    EventChannel

    他们的功能以及使用方式与MethodChannel相似

    MethodChannel,BasicMessageChannel,EventChannel的区别与选择

    • MethodChannel 使用异步的方式与原生进行交流,用于比如需要调用原生的某些功能,但是原生需要耗时返回的情况,这种事有返回值的调用,支持数据双向传递
    • EventChannel 是用来返回监听各个阶段的状态,没有返回值,并且只支持单向,只支持原生传递数据给Flutter,可以用来监听某些特殊原生功能的状态
    • BasicMessageChannel 用于传递字符串和半结构化的消息

    欢迎关注Mike的简书

    Android 知识整理

    相关文章

      网友评论

          本文标题:Fiutter- 混合开发与原生Android交互

          本文链接:https://www.haomeiwen.com/subject/xpqkaltx.html