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

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | 完整代码示例 )相关的知识,希望对你有一定的参考价值。

前言

前置博客 :

执行效果 :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");
            }
        });

    }

}




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





三、相关资源



参考资料 :