最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Flutter学习之旅-混合开发Part1

    正文概述 掘金(沐小枫)   2020-12-30   517

    Flutter学习之旅-混合开发Part1

    场景

    Flutter学习之旅-混合开发Part1

    平台通道数据类型支持

    DartAndroidiOS
    nullnullnil (NSNull when nested)booljava.lang.BooleanNSNumber numberWithBool:intjava.lang.IntegerNSNumber numberWithInt:int, 如果不足32位java.lang.LongNSNumber numberWithLong:int, 如果不足64位java.math.BigIntegerFlutterStandardBigIntegerdoublejava.lang.DoubleNSNumber numberWithDouble:Stringjava.lang.StringNSStringUint8Listbyte[]FlutterStandardTypedData typedDataWithBytes:Int32Listint[]FlutterStandardTypedData typedDataWithInt32:Int64Listlong[]FlutterStandardTypedData typedDataWithInt64:Float64Listdouble[]FlutterStandardTypedData typedDataWithFloat64:Listjava.util.ArrayListNSArrayMapjava.util.HashMapNSDictionary

    当在发送和接收值时,这些值在消息中的序列化和反序列化会自动进行。

    平台通道

    Platform Channel 是所以 Flutter 提供的和平台端通信的工具,针对不同的使用场景,Platform Channel 又分为以下三类:

    1. Message channel:用于传递字符串和半结构化的信息,支持使用自定义消息编解码器进行基本的异步消息传递
    2. Method channel:用于传递方法调用(method invocation)
    3. Event channel:用于数据流(event streams)的通信,通常用在需要进行实时监听的使用场景,比如:网络状态,电池充电状态以及一些监听器的实现

    Flutter项目中需要与Native进行通信-实战

    我们这里仅使用Method channel和Event channel进行通信实战

    要实现的功能:

    1. Flutter给Native传递三个参数,Native要把这三个参数相加得到的结果返回给Flutter,并显示在Flutter界面上
    2. Native写一个定时器,每隔1秒进行“+1操作”,每次“+1”后,把结果传递给Flutter,当结果大于30的时候结束定时器
    功能1:
    Android端:

    创建MethodChannelDemo.kt

    class MethodChannelDemo (messenger: BinaryMessenger): MethodChannel.MethodCallHandler{
    
        private var channel: MethodChannel = MethodChannel(messenger, "com.mufeng.flutterNativeChannel.MethodChannel")
    
        init {
            channel.setMethodCallHandler(this)
        }
    
        override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
            when(call.method){
                "add" -> {
                    val params1 = call.argument<Int>("params1")
                    val params2 = call.argument<Int>("params2")
                    val params3 = call.argument<Int>("params3")
                    val params = params1!! + params2!! + params3!!
                    result.success(params)
                }
            }
        }
    }
    

    在MainActivity中启动平台通道

    class MainActivity: FlutterActivity() {
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            MethodChannelDemo(flutterEngine.dartExecutor.binaryMessenger)
        }
    }
    
    iOS端

    创建MethodChannelDemo.swift

    //
    //  MethodChannelDemo.swift
    //  Runner
    //
    //  Created by a on 2020/12/28.
    //
    
    import Foundation
    
    import Flutter
    import UIKit
    
    public class MethodChannelDemo {
        init(messenger: FlutterBinaryMessenger) {
            let channel = FlutterMethodChannel(name: "com.mufeng.flutterNativeChannel.MethodChannel", binaryMessenger: messenger)
            channel.setMethodCallHandler{ (call: FlutterMethodCall, result:@escaping FlutterResult)in
                if(call.method == "add"){
                    if let dict = call.arguments as? Dictionary<String, Any>{
                        let params1: Int = dict["params1"] as? Int ?? 0
                        let params2: Int = dict["params2"] as? Int ?? 0
                        let params3: Int = dict["params3"] as? Int ?? 0
                        result(params1 + params2 + params3)
                    }
                }
            }
        }
    }
    
    

    在 AppDelegate 中启动平台通道:

    import UIKit
    import Flutter
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        
        /// start
        let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
        MethodChannelDemo(messenger: controller.binaryMessenger)
        /// end
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }
    

    在ios中也用同样的操作,要保证平台通道的channel保持一致,这样在Flutter中就可以保证一套代码试用两个平台了

    Flutter
     /// 保证平台channel保持一致
     var channel = MethodChannel('com.mufeng.flutterNativeChannel.MethodChannel');
     var result = await channel.invokeMethod('add', {'params1': int.parse(controller1.text), 'params2': int.parse(controller2.text), 'params3': int.parse(controller3.text)});
     setState(() {
       this.result = result.toString();
     });
    
    显示结果:

    Android: Flutter学习之旅-混合开发Part1 iOS: Flutter学习之旅-混合开发Part1

    功能2:
    Android端

    android 下创建 EventChannelDemo:

    package com.mufeng.flutter_native_channel
    
    import android.app.Activity
    import io.flutter.plugin.common.BinaryMessenger
    import io.flutter.plugin.common.EventChannel
    import java.util.*
    import kotlin.concurrent.timerTask
    
    class EventChannelDemo(private var activity: Activity, messenger: BinaryMessenger) : EventChannel.StreamHandler {
    
        private var channel: EventChannel = EventChannel(messenger, "com.mufeng.flutterNativeChannel.EventChannel")
        private var count = 0
        private var events: EventChannel.EventSink? = null
        init {
            channel.setStreamHandler(this)
            startTimer()
        }
    
        private fun startTimer() {
            var timer = Timer().schedule(timerTask {
                count++
                val map = mapOf("count" to count)
                activity.runOnUiThread {
                    // 必须运行在主线程
                    events?.success(map)
                }
                if(count >= 30){
                     activity.runOnUiThread {
                        events?.error("400", "超过30秒,倒计时结束", null)
                    }
                    cancel()
                }
            }, 0, 1000)
        }
    
        override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
            this.events = events
        }
    
        override fun onCancel(arguments: Any?) {
            this.events = null
        }
    }
    

    在 MainActivity 启动:

    class MainActivity: FlutterActivity() {
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            // MethodChannelDemo(flutterEngine.dartExecutor.binaryMessenger)
            EventChannelDemo(this, flutterEngine.dartExecutor.binaryMessenger)
        }
    }
    
    iOS端

    ios 下创建 EventChannelDemo

    
    import Foundation
    import Flutter
    import UIKit
    
    public class EventChannelDemo: NSObject, FlutterStreamHandler {
        var channel: FlutterEventChannel?
        var count = 0
        var events: FlutterEventSink?
        var timer: Timer?
        
        public override init() {
            super.init()
        }
        
        convenience init(messenger: FlutterBinaryMessenger) {
            self.init()
            
            channel = FlutterEventChannel(name: "com.mufeng.flutterNativeChannel.EventChannel", binaryMessenger: messenger)
            channel?.setStreamHandler(self)
            startTimer()
        }
        
        func startTimer() {
            timer = Timer.scheduledTimer(timeInterval: 1, target: self,selector: #selector(self.tickDown),userInfo: nil,repeats: true)
        }
        
        @objc func tickDown(){
            count += 1
            let args = ["count": count]
            if(events != nil){
                events!(args)
            }
            if(count >= 30){
                if(events != nil){
                    events!(FlutterError.init(code: "400", message: "超过30秒,倒计时结束", details: nil))
                }
                timer?.fireDate = Date.distantFuture
                timer?.invalidate()
            }
        }
        
        public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
            self.events = events
            return nil
        }
        
        public func onCancel(withArguments arguments: Any?) -> FlutterError? {
            self.events = nil
            timer?.invalidate()
            self.timer = nil
            return nil
        }
    }
    

    在 AppDelegate 启动:

    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        
        let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
        // MethodChannelDemo(messenger: controller.binaryMessenger)
        EventChannelDemo(messenger: controller.binaryMessenger)
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }
    
    
    Flutter端
    var _eventChannel = EventChannel('com.mufeng.flutterNativeChannel.EventChannel');
    
    _eventChannel.receiveBroadcastStream().listen(_listen, onError: (value){
          print(value);
        });
        
      void _listen(event) {
        setState(() {
          second = event['count'].toString();
        });
      }
    
    显示结果

    Android:

    // 打印出原生发挥的错误信息
    I/flutter (24053): PlatformException(400, 超过30秒,倒计时结束, null, null)
    

    Flutter学习之旅-混合开发Part1 iOS:

    // 打印出原生发挥的错误信息
    flutter: PlatformException(400, 超过30秒,倒计时结束, null, null)
    

    Flutter学习之旅-混合开发Part1

    源码地址:flutter_native_channel

    总结

    感谢


    起源地下载网 » Flutter学习之旅-混合开发Part1

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元