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

举报
韩曙亮 发表于 2022/01/13 23:20:37 2022/01/13
【摘要】 文章目录 前言一、Android 端完整代码示例二、Flutter 端完整代码示例三、相关资源 前言 前置博客 : 【Flutter】Flutter 混合开发 ( Flutter 与 N...

前言

前置博客 :

执行效果 : 在 Android 端嵌入 FlutterFragment , 通过 3 3 3 种不同的 Channel 进行 Android 端 与 Flutter 端进行通信 ;

请添加图片描述





一、Android 端完整代码示例



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");
            }
        });

    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220




二、Flutter 端完整代码示例



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.
    );
  }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185




三、相关资源



参考资料 :


重要的专题 :


博客源码下载 :

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/119998492

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。