Skip to content

Flutter Add-to-app Android Support Library For Tars RPC framework

License

Notifications You must be signed in to change notification settings

brooklet/TarsFlutterAndroid

Repository files navigation

TarsFlutterAndroid

Flutter Add-to-app Android Support Library For Tars RPC framework

在Flutter模块集成到已有Android应用模式下,实现在Flutter模块和Android原生层之间传递Tars对象

如果你是直接在Flutter模块中使用Tars协议或者TUP协议请求后端数据接口,不需要使用本项目,直接使用这个项目https://pub.dev/packages/tars_flutter


引入方法

  1. 在Android的app模块build.gradle中添加:
repositories {
    maven { url 'https://jitpack.io' }
}

dependencies {
    implementation 'com.github.brooklet:TarsFlutterAndroid:v1.0.0-beta.3'
}
  1. 在Flutter模块pubspec.yaml中添加:
dependencies:
  tars_flutter: ^0.1.0

  1. Tars定义文件转dart文件的方法,参考 https://pub.dev/packages/tars_flutter

快速入门

  1. Android 的 MyApplication 中初始化 FlutterEngineGroup

    
    class MyApplication : Application() {
        lateinit var engines: FlutterEngineGroup
        ...
    
        override fun onCreate() {
            ...
    
            engines = FlutterEngineGroup(this)
        }
    }
    
    
  2. 页面直接继承封装好的:BaseFlutterActivity 或者 BaseFlutterFragment,需实现如下方法:

        // 注册可供flutter调用的TarsMethodChannel方法列表
        abstract fun getMethodCallHandlers(): List<TarsMethodChannel.MethodHandler>
    
        // 定义TarsMethodChannel的名称,需要与flutter中一致
        abstract fun getChannelName(): String
    
        // 定义flutter中的页面的入口名称, 需要与flutter中一致,
        // 如'testPage' 对应 flutter @pragma('vm:testPage')
        abstract fun getEntrypoint(): String
    
        // 获得 FlutterEngineGroup
        abstract fun getFlutterEngineGroup(): FlutterEngineGroup
    
    
     实例如下:
    
        // 注册可供flutter调用的方法
        override fun getMethodCallHandlers(): List<TarsMethodChannel.MethodHandler> {
            return mutableListOf(
                TarsMethodChannel.MethodHandler(
                    "getCount", RegisterParameter0()
                ) { methodCall, result ->
                    run {
                        val rsp = TestRsp()
                        rsp.id = count.toLong()
                        result.success(InvokeArgument1(rsp))
                    }
                },
    
                TarsMethodChannel.MethodHandler(
                    "updateCount", RegisterParameter1(TestReq::class.java)
                ) { methodCall, result ->
                    run {
                        Log.d("MainActivity", "call method: updateCount.")
                        val req = (methodCall.arguments as InvokeArgument1).arg1 as TestReq
                        count += req.id
                        val rsp = TestRsp()
                        rsp.id = count.toLong()
                        result.success(InvokeArgument1(rsp))
                    }
                }
            )
        }
    
        // 定义TarsMethodChannel的名称,需要与flutter中一致
        override fun getChannelName(): String {
            return "test"
        }
        
        // 定义flutter中的页面的入口名称, 需要与flutter中一致,
        // 如'testPage' 对应 flutter @pragma('vm:testPage')
        override fun getEntrypoint(): String {
            return "testPage"
        }
    
        // 获得 FlutterEngineGroup
        override fun getFlutterEngineGroup(): FlutterEngineGroup {
            return MyApplication.getInstance().engines
        }
    
    
    

    核心代码解析:

    TarsMethodChannel.MethodHandler(
                    "updateCount", RegisterParameter1(TestReq::class.java)
                ) { methodCall, result ->
                    run {
                        Log.d("MainActivity", "call method: updateCount.")
                        val req = (methodCall.arguments as InvokeArgument1).arg1 as TestReq
                        count += req.id
                        val rsp = TestRsp()
                        rsp.id = count.toLong()
                        result.success(InvokeArgument1(rsp))
                    }
                }
    

    表示注册一个方法:方法名为updateCount,方法参数声明为RegisterParameter1(TestReq::class.java),表示有1个请求参数,参数TestReq类型. 方法的返回值为InvokeArgument1(rsp),表示有1个返回值,类型为TestRsp

  3. 在 Flutter模块中创建 TarsMethodChannel 对象,并注册Android原生层可以调用的方法列表

        late TarsMethodChannel _channel;
    
        @override
        void initState() {
            super.initState();
            _channel = TarsMethodChannel('test');
            registerMethodCallHandlers();
            ...
        }
    
        //注册回调函数
        void registerMethodCallHandlers() {
            _channel.registerMethodCallHandlers([
            //onCountChange begin
            MethodHandler("onCountChange", RegisterParameter1(TestReq()),
                (TarsMethodCall call) async {
                logger.d("message");
                var req = (call.arguments as InvokeArgument1).arg1 as TestReq;
                _counter = req.id;
                logger.d("get onCountChange call: $_counter");
    
                setState(() {});
            }),
            //onCountChange end
            //add more...
            ]);
        }
    
    

    核心代码解析

    MethodHandler("onCountChange", RegisterParameter1(TestReq()),
        (TarsMethodCall call) async {
        logger.d("message");
        var req = (call.arguments as InvokeArgument1).arg1 as TestReq;
        _counter = req.id;
        logger.d("get onCountChange call: $_counter");
    
        setState(() {});
    }),
    

    表示注册一个方法:方法名为onCountChange,方法参数声明为RegisterParameter1(TestReq()),表示有1个请求参数,参数TestReq类型. 方法的无返回值. 注意,对比Android原生侧的代码,RegisterParameter1(TestReq())里面的TestReq()是传入的对象,而不是class

  4. 在Android中调用Flutter方法的方式(示例)

        val req = TestReq()
        req.id = count
        channel.invokeMethod("onCountChange", InvokeArgument1(req))
    

    代码解析,channel.invokeMethod("onCountChange", InvokeArgument1(req))表示调用Flutter模块的onCountChange方法, 实际参数req必须包在InvokeArgument1中,与Flutter模块注册的方法一致

    其中TestReq是Tars协议的结构体.

  5. 在Flutter中调用Android方法的方式(示例)

        Future<void> _incrementCounter() async {
            var req = TestReq();
            req.id = 1;
            var response = await _channel.invokeMethod<InvokeArgument1>("updateCount",
                InvokeArgument1(req), false, RegisterParameter1(TestRsp()));
            var rsp = response!.arg1 as TestRsp;
            _counter = rsp.id;
            logger.d("updateCount: $_counter");
            setState(() {});
        }
    

    代码解析,var response = await _channel.invokeMethod<InvokeArgument1>("updateCount",InvokeArgument1(req), false, RegisterParameter1(TestRsp())),表示调用Android的updateCount方法, 实际参数req必须包在InvokeArgument1中,与Android注册的方法一致. 注意,RegisterParameter1(TestRsp())表示方法的返回值的类型,TestRsp()是传入的对象,而不是class

    其中TestReqTestRsp 都是Tars协议的结构体


用法说明

  1. TarsMethodChannel是在Flutter自带的MethodChannel基础增加了对Tars对象的支持。

  2. 相比MethodChannel的调用方式,TarsMethodChannel增加了InvokeArgumentRegisterParameter参数。

  3. InvokeArgument是调用方用来封装多个调用参数或者返回值,包括InvokeArgument0InvokeArgument1InvokeArgument2InvokeArgument3四个子类,分别对应0..3个参数的情况。

  4. RegisterParameter是被调用方用来注册多个被调用参数或者返回值,包括RegisterParameter0RegisterParameter1RegisterParameter2RegisterParameter3四个子类,分别对应0..3个参数的情况。

  5. 注意 在Flutter中,InvokeArgumentRegisterParameter 的参数都必须是 对象,而不是类,在Android中RegisterParameter 的参数可以是类。

  6. 调用方的InvokeArgument必须和被调用方的RegisterParameter的类型及参数匹配,比如InvokeArgument2(TestReq(),"")与之相应的被调用方注册的方法参数必须是RegisterParameter2(TestReq(),"")


高级用法

  1. 在Android原生端可以不继承BaseFlutterActivity 或者 BaseFlutterFragment,对比Flutter官方的代码,只需要使用TarsMethodChannel替换MethodChannel即可,例如:
channel =
            TarsMethodChannel(
                engine.dartExecutor.binaryMessenger,
                mFlutterMethodChannel.getChannelName()
            )

备注

此框架仅支持AndroidX和Flutter 2.2.0及以上版本

详细用法参考 example

About

Flutter Add-to-app Android Support Library For Tars RPC framework

Resources

License

Stars

Watchers

Forks

Packages

No packages published