Flutter与Android原生Activity交互及传递​​数据

上一篇中:Flutter 使用AndroidStudio并集成Flutter界面_flutter3.0 android跳转到flutter界面-CSDN博客,学习了 Android 原生集成 Flutter 并实现了页面跳转本篇将要学习Flutter与Activity之间的数据交互。


Platform Channel 跨平台通讯

三种不同的 Channel:

  • MethodChannel:用于Flutter和原生方法映射调用;
  • EventChannel:用于Flutter和Native进行事件监听、取消等。
  • BasicMessageChannel:用于Flutter和Native进行消息数据交换时。

但无论是传递方法、事件,其本质上都是数据的传递。每种 Channel 均包含三个成员变量:

  • name:代表 Channel 唯一标识符,Channel 可以包含多个,但 name 是唯一的;
  • messager:代表消息发送与接收的工具 BinaryMessenger
  • codec:代表消息的编解码器;

BinaryMessenger

BinaryMessenger是PlatformChannel与Flutter端的通信的工具,其通信使用的消息格式为二进制格式数据,BinaryMessenger在Android中是一个接口,它的实现类为FlutterNativeView。

Codec

Codec是消息编解码器,主要用于将二进制格式的数据转化为Handler能够识别的数据。Flutter定义了两种Codec:

  • MessageCodec用于二进制格式数据与基础数据之间的编解码,BasicMessageChannel所使用的编解码器是MessageCodec。

  • MethodChannel和EventChannel所使用的编解码均为MethodCodec。

Handler

Flutter定义了三种类型的Handler,它们与PlatformChannel类型一一对应,分别是MessageHandler、MethodHandler、StreamHandler。

使用PlatformChannel时,会为它注册一个Handler,PlatformChannel会将该二进制数据通过Codec解码为转化为Handler能够识别的数据,并交给Handler处理。当Handler处理完消息之后,会通过回调函数返回result,将result通过编解码器编码为二进制格式数据,通过BinaryMessenger发送回Flutter端。


MethodChannel

  • Flutter中调用MethodChannel.invokeMethod()实现跳转及参数传递到原生Activity页面。
  • 原生页面调用MethodChannel.setMethodCallHandler()接受Flutter传递的消息。

Android 代码

Android端创建MethodChannel需要传递2个参数。第1个是BinaryMessenger接口,代表消息信使,是消息发送与接收的工具;第二个参数是name,表示Channel的名称,定义了final类型保证唯一,与Flutter的MethodChannel呼应上。

private static final String CHANNEL_NATIVE = "com.example.flutter/native";
private FlutterEngine flutterEngine;
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_takeout);
        
        flutterEngine = new FlutterEngine(this);
        flutterEngine.getNavigationChannel().setInitialRoute("route1");
        flutterEngine.getDartExecutor().executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
        );

        flutterView = new FlutterView(this);
        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        FrameLayout flContainer = findViewById(R.id.flutter_view);
        flContainer.addView(flutterView, lp);

        if (flutterEngine!=null){
            flutterView.attachToFlutterEngine(flutterEngine);
        }

        MethodChannel nativeChannel = new MethodChannel(flutterEngine.getDartExecutor()
                                      .getBinaryMessenger(), CHANNEL_NATIVE);
        nativeChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                switch (methodCall.method) {
                    case "jumpToNative":   // 跳转原生页面
                        if (methodCall.arguments != null) {
                            ToastUtil.show(TAG,  methodCall.argument("message"));
                        } else {
                            ToastUtil.show(TAG,"回调参数为空");
                        }
                        startActivity(new Intent(TAG, MainPageActivity.class));

                        result.success("Activity -> Flutter 接收回调的返回值成功");
                        break;
                    default:
                        result.notImplemented();
                        break;
                }
            }
        });
}
    @Override
    protected void onResume() {
        super.onResume();
        if (flutterEngine!=null){
            flutterEngine.getLifecycleChannel().appIsResumed();
        }
    }
    @Override
    protected void onPause() {
        super.onPause();
        if (flutterEngine!=null){
            flutterEngine.getLifecycleChannel().appIsInactive();
        }

    }
    @Override
    protected void onStop() {
        super.onStop();
        if (flutterEngine!=null){
            flutterEngine.getLifecycleChannel().appIsPaused();
        }
    }

Flutter代码

使用MethodChannel需要引入services.dart包,Channel名称要和Android端定义的相同。调用invokeMethod()。

class _MyHomePageState extends State<MyHomePage> {
  static const nativeChannel = const MethodChannel('com.example.flutter/native');
  String _result = '';
  Future<void> _incrementCounter() async {
    Map<String, dynamic> result = {'message': '我从Flutter页面回来了'};
    try {
      _result = await nativeChannel.invokeMethod('jumpToNative', result);
    } on PlatformException catch (e) {
      _result = "Failed: '${e.message}'.";
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title), ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('传递结果:$_result',),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Flutter返回上一页:传递数据

Navigator.canPop(context)判断是否可以返回,true 就调用返回,false 则说明当前已经是第一个页面了,就跳转到Activity。代码实例如下:

FlutterView页面添加按钮:跳转到SecondPage页面

RaisedButton(
    child: Text('跳转Flutter页面'),
    onPressed: () {
      Navigator.of(context).push(MaterialPageRoute(builder: (context) {
        return SecondPage();
      }));
    }
),

 调用Navigator.canPop(context) 判断:

static const nativeChannel =const MethodChannel('com.example.flutter/native');
static const flutterChannel =const MethodChannel('com.example.flutter/flutter');

@override
void initState() {
  super.initState();
  Future<dynamic> handler(MethodCall call) async {
    switch (call.method) {
      case 'goBack':
        if (Navigator.canPop(context)) {  // 返回上一页
          Navigator.of(context).pop();
        } else {
          nativeChannel.invokeMethod('goBack');
        }
        break;
    }
  }
  flutterChannel.setMethodCallHandler(handler);
}

在Activity重写onBackPressed()方法,将返回键的事件处理交给Flutter端。

private static final String CHANNEL_FLUTTER = "com.example.flutter/flutter";

@Override
public void onBackPressed() {
    MethodChannel flutterChannel = new MethodChannel(flutterView, CHANNEL_FLUTTER);
    flutterChannel.invokeMethod("goBack", null);
}

原生的MethodCallHandler回调,调用该方法直接finish掉Activity。

nativeChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
switch (methodCall.method) {
    case "goBack":
        // 返回上一页
        finish();
        break;
    default:
        result.notImplemented();
        break;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾阳Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值