前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | 完整代码示例 )

【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | 完整代码示例 )

作者头像
韩曙亮
发布2023-03-29 16:00:53
2.2K0
发布2023-03-29 16:00:53
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

前言

前置博客 :

执行效果 : 在 Android 端嵌入 FlutterFragment , 通过

3

种不同的 Channel 进行 Android 端 与 Flutter 端进行通信 ;

一、Android 端完整代码示例


代码语言:javascript
复制
package com.example.flutter_native;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterFragment;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StringCodec;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Flutter MainActivity";


    /**
     * 嵌入到 Activity 界面的 FlutterFragment
     */
    private FlutterFragment mFlutterFragment;

    /**
     * 显示收发消息的组件
     */
    private TextView show_message;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        show_message = findViewById(R.id.show_message);

        findViewById(R.id.flutter1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentTransaction fragmentTransaction =
                        getSupportFragmentManager().beginTransaction();

                // 使用该方法创建的 Fragment 没有传递数据
                //FlutterFragment.createDefault()
                // 打开默认界面
                //fragmentTransaction.replace(R.id.frame, FlutterFragment.createDefault());

                mFlutterFragment = FlutterFragment.withNewEngine().
                        initialRoute("嵌入 FlutterFragment").build();

                Log.i(TAG, "mFlutterFragment : " + mFlutterFragment);

                // 创建 FlutterFragment
                fragmentTransaction.replace(R.id.frame, mFlutterFragment);
                fragmentTransaction.commit();

                //initBasicMessageChannel();

                new Thread(){
                    @Override
                    public void run() {
                        try {
                            sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        initBasicMessageChannel();
                        initEventChannel();
                        initMethodChannel();

                        Log.i(TAG, "mFlutterFragment : " + mFlutterFragment);

                    }
                }.start();
            }
        });

        findViewById(R.id.flutter2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = FlutterActivity
                        .withNewEngine()
                        .initialRoute("启动 FlutterActivity")
                        .build(MainActivity.this);
                intent.putExtra("initParams", "启动 FlutterActivity2");
                startActivity(intent);
            }
        });



    }


    /**
     * BasicMessageChannel 消息传递通道
     */
    private BasicMessageChannel mBasicMessageChannel;

    /**
     * 初始化 BasicMessageChannel
     */
    private void initBasicMessageChannel() {
        // 初始化
        mBasicMessageChannel = new BasicMessageChannel(
                mFlutterFragment.getFlutterEngine().getDartExecutor(),
                "BasicMessageChannel",
                StringCodec.INSTANCE);

        // 设置消息接收监听
        mBasicMessageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<String>() {
            @Override
            public void onMessage(@Nullable String message, @NonNull BasicMessageChannel.Reply reply) {
                show_message.setText("Dart 通过 BasicMessageChannel 通道向 Native 发送 " + message + " 信息");
            }
        });

        // 点击按钮发送消息 , 并设置 Reply 接收 Dart 返回的消息
        findViewById(R.id.channel1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mBasicMessageChannel.send(
                        "Native 通过 BasicMessageChannel 通道发送消息 Hello !",
                        new BasicMessageChannel.Reply() {
                            @Override
                            public void reply(@Nullable Object reply) {
                                show_message.setText("Native 通过 BasicMessageChannel 通道发送消息 Hello 后 , Dart 反馈的信息 ");
                            }
                        }
                );
            }
        });
    }

    /**
     * 与 Flutter 进行消息交互的通道
     */
    private EventChannel mEventChannel;

    private EventChannel.EventSink mEventSink;

    /**
     * 初始化 EventChannel
     */
    private void initEventChannel() {
        // 初始化 EventChannel 实例对象
        mEventChannel = new EventChannel(
                mFlutterFragment.getFlutterEngine().getDartExecutor(),
                "EventChannel");

        Log.i(TAG, "mEventChannel 初始化成功 , mEventChannel : " + mEventChannel);

        mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
            /**
             * 事件流建立成功会回调该方法
             * @param arguments
             * @param events
             */
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                mEventSink = events;
                Log.i(TAG, "事件流建立成功");
            }

            @Override
            public void onCancel(Object arguments) {
                mEventSink = null;
            }
        });

        Log.i(TAG, "mEventChannel StreamHandler 设置完成");

        findViewById(R.id.channel2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "Native 通过 EventChannel 通道发送消息 , mEventSink : " + mEventSink);
                // 点击按钮 , 向 Flutter 端发送数据
                if (mEventSink != null) {
                    mEventSink.success("Native 通过 EventChannel 通道发送消息 Hello !");
                }
            }
        });
    }


    /**
     * 方法调用消息通道
     */
    private MethodChannel mMethodChannel;

    /**
     * 初始化 MethodChannel
     */
    private void initMethodChannel() {
        mMethodChannel = new MethodChannel(mFlutterFragment.getFlutterEngine().getDartExecutor(), "MethodChannel");

        mMethodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
                show_message.setText("Dart 端通过 MethodChannel 调用 Android 端的 " + call.method + " 方法 , 参数是 " + call.arguments);
            }
        });

        findViewById(R.id.channel3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMethodChannel.invokeMethod("method", "arguments");
            }
        });

    }

}

二、Flutter 端完整代码示例


代码语言:javascript
复制
import 'dart:async';

import 'package:flutter/material.dart';

// 使用 window.defaultRouteName 必须导入当前 UI 库
import 'dart:ui';

import 'package:flutter/services.dart';

void main() => runApp(
    /// 该构造方法中传入从 Android 中传递来的参数
    MyApp(initParams: window.defaultRouteName,)
);

class MyApp extends StatelessWidget {
  /// 这是从 Android 中传递来的参数
  final String initParams;
  /// 构造方法 , 获取从 Android 中传递来的参数
  const MyApp({Key? key, required this.initParams}):super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: "初始参数 : $initParams"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  /// 展示从 Native 获取的消息
  String showMessage = "";

  static const BasicMessageChannel _basicMessageChannel =
    const BasicMessageChannel('BasicMessageChannel', StringCodec());

  static const MethodChannel _methodChannel =
    const MethodChannel('MethodChannel');

  static const EventChannel _eventChannel =
    EventChannel('EventChannel');

  /// 监听 EventChannel 数据的句柄
  late StreamSubscription _streamSubscription;

  /// 当前使用的消息通道是否是 MethodChannel
  bool _isMethodChannel = false;

  @override
  void initState() {
    /// 从 BasicMessageChannel 通道获取消息
    _basicMessageChannel.setMessageHandler((message) => Future<String>((){
      setState(() {
        showMessage = "BasicMessageChannel : $message";
      });
      return "BasicMessageChannel : $message";
    }));

    /// 这里延迟 6 秒在注册该事件
    ///   一定要先在 Android 中设置好 EventChannel
    ///   然后 , 才能在 Flutter 中设置监听
    ///   否则 , 无法成功
    Future.delayed(const Duration(milliseconds: 6000), () {
      // Here you can write your code

      // 注册 EventChannel 监听
      _streamSubscription = _eventChannel
          .receiveBroadcastStream()
      /// StreamSubscription<T> listen(void onData(T event)?,
      ///   {Function? onError, void onDone()?, bool? cancelOnError});
          .listen(
        /// EventChannel 接收到 Native 信息后 , 回调的方法
            (message) {
              print("Flutter _eventChannel listen 回调");
              setState(() {
                /// 接收到消息 , 显示在界面中
                showMessage = message;
              });
          },
          onError: (error){
            print("Flutter _eventChannel listen 出错");
            print(error);
          }
      );

      setState(() {
      });

    });

    // Future<dynamic> Function(MethodCall call)? handler
    _methodChannel.setMethodCallHandler((call) {
      var method = call.method;
      var arguments = call.arguments;
      setState(() {
        showMessage = "Android 端通过 MethodChannel 调用 Flutter 端 $method 方法, 参数为 $arguments";
      });
      return Future.value();
    });


    /*// 注册 EventChannel 监听
    _streamSubscription = _eventChannel
        .receiveBroadcastStream()
        /// StreamSubscription<T> listen(void onData(T event)?,
        ///   {Function? onError, void onDone()?, bool? cancelOnError});
        .listen(
          /// EventChannel 接收到 Native 信息后 , 回调的方法
          (message) {
            print("Flutter _eventChannel listen 回调");
            setState(() {
              /// 接收到消息 , 显示在界面中
              showMessage = message;
            });
          },
          onError: (error){
            print("Flutter _eventChannel listen 出错");
            print(error);
          }
        );*/

    print("Flutter _eventChannel 注册完毕");

    super.initState();
  }

  @override
  void dispose() {
    // 取消监听
    _streamSubscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        alignment: Alignment.topCenter,
        decoration: BoxDecoration(color: Colors.amber),
        margin: EdgeInsets.only(top: 0),
        child: Column(
          children: [

            ElevatedButton(
            onPressed: (){
              _basicMessageChannel.send("Dart 端通过 BasicMessageChannel 向 Android 端发送消息 Hello !");
            },
              child: Text("BasicMessageChannel 向 Android 发送消息"),
            ),

            ElevatedButton(
              onPressed: (){
                _methodChannel.invokeMethod("method", "arguments");
              },
              child: Text("MethodChannel 调用 Android 方法"),
            ),

            Container(
              color: Colors.black,
              child: Text(
                "Native 传输的消息 : $showMessage",
                style: TextStyle(color: Colors.green),),
            ),

          ],
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

三、相关资源


参考资料 :

重要的专题 :

博客源码下载 :

  • GitHub 地址 : ( 随博客进度一直更新 , 有可能没有本博客的源码 )
代码语言:txt
复制
- **Flutter Module 工程 :** [https://github.com/han1202012/flutter\_module](https://github.com/han1202012/flutter_module)
- **Android 应用 :** [https://github.com/han1202012/flutter\_native](https://github.com/han1202012/flutter_native)
- **注意 : 上面两个工程要放在同一个目录中 , 否则编译不通过 ;**
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 前言
  • 一、Android 端完整代码示例
  • 二、Flutter 端完整代码示例
  • 三、相关资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档