Flutter与Android原生混合开发——EventChannel与MethodChannel的使用

在使用Flutter开发app时,会遇到跟Android原生系统API交互的情况,
通常可以使用Flutter来写页面,复用原来已有的Android的逻辑(如自己的或者第三方的SDK),来加快开发进度。
可以使用插件来解决,官网关于插件的开发介绍:
撰写双端平台代码(插件编写实现)

文中列出了一个完整的demo:
注意:可在 /examples/platform_channel/ 中获得使用 Java 实现的 Android 及使用 Objective-C 实现的 iOS 的该示例完整可运行的代码。对于用 Swift 实现的 iOS 代码,请参阅 /examples/platform_channel_swift/


Channel

Flutter定义了三种不同类型的Channel,它们分别是

  • BasicMessageChannel:用于传递字符串和半结构化的信息,可以双向的请求数据。
  • MethodChannel:用于传递方法调用(method invocation,即Flutter端可以调用Platform端的方法并通过Result接口回调结果数据。
  • EventChannel: 用于数据流(event streams)的通信,即Flutter端监听Platform端的实时消息,一旦Platform端产生了数据,立即回调到Flutter端。

⚠️注意:在Android和iOS平台上,Platform Task Runner跑在主线程上。因此,不应该在Platform端的Handler中处理耗时操作。

先看一下MethodChannel和EventChannel的使用
main.dart文件如下:

class PlatformChannel extends StatefulWidget {
  @override
  _PlatformChannelState createState() => _PlatformChannelState();
}

class _PlatformChannelState extends State<PlatformChannel> {
  static const MethodChannel methodChannel =
      MethodChannel('samples.flutter.io/battery');
  static const EventChannel eventChannel =
      EventChannel('samples.flutter.io/charging');

  String _batteryLevel = 'Battery level: unknown.';
  String _chargingStatus = 'Battery status: unknown.';

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await methodChannel.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level: $result%.';
    } on PlatformException {
      batteryLevel = 'Failed to get battery level.';
    }
    setState(() {
      _batteryLevel = batteryLevel;
    });
  }

  @override
  void initState() {
    super.initState();
    eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
  }

  void _onEvent(Object event) {
    setState(() {
      _chargingStatus =
          "Battery status: ${event == 'charging' ? '' : 'dis'}charging.";
    });
  }

  void _onError(Object error) {
    setState(() {
      _chargingStatus = 'Battery status: unknown.';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(_batteryLevel, key: const Key('Battery level label')),
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: RaisedButton(
                  child: const Text('Refresh'),
                  onPressed: _getBatteryLevel,
                ),
              ),
            ],
          ),
          Text(_chargingStatus),
        ],
      ),
    );
  }
}

void main() {
  runApp(MaterialApp(home: PlatformChannel()));
}

1. 使用MethodChannel步骤

  • 其中定义了一个MethodChannel对象,使用methodChannelinvokeMethod('getBatteryLevel')方法可以调用到Android原生的方法,
  • 在Android定义MethodChannel对象,并调用其setMethodCallHandler方法,在回调接口MethodCallHandler中实现onMethodCall方法,通过Result对象回传值到Flutter端。
  private static final String BATTERY_CHANNEL = "samples.flutter.io/battery";



    new MethodChannel(getFlutterView(), BATTERY_CHANNEL).setMethodCallHandler(
        new MethodCallHandler() {
          @Override
          public void onMethodCall(MethodCall call, Result result) {
            if (call.method.equals("getBatteryLevel")) {
              int batteryLevel = getBatteryLevel();

              if (batteryLevel != -1) {
                result.success(batteryLevel);
              } else {
                result.error("UNAVAILABLE", "Battery level not available.", null);
              }
            } else {
              result.notImplemented();
            }
          }
        }
    );

在该MethodCallHandler回调中处理Flutter部分发来的方法调用请求,并通过result.success(batteryLevel)传递回数据。

这是直接能获取到Android端立即返回值的情况,但是通常Android端是异步操作,并在接口回调中返回值,那这时如何将值再传递到Flutter端呢?这时就可以使用EventChannel了。

2. 使用EventChannel步骤

  • 在Android端定义EventChannel对象,并调用setStreamHandler()方法,在匿名内部类StreamHandler里实现onListen和onCancel方法,通过EventSink对象来回传数据到Flutter端,
  • Flutter端通过 eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);来定义_onEvent函数和_onError函数处理传回的值。
  new EventChannel(getFlutterView(), CHARGING_CHANNEL).setStreamHandler(
        new StreamHandler() {
          private BroadcastReceiver chargingStateChangeReceiver;
          @Override
          public void onListen(Object arguments, EventSink events) {
            chargingStateChangeReceiver = createChargingStateChangeReceiver(events);
            registerReceiver(
                chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
          }

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

3. 使用BasicMessageChannel步骤

Android端:
在这里插入图片描述
dart端:

在这里插入图片描述

参考:
Flutter Platform channel详解
深入理解Flutter Platform Channel

发布了82 篇原创文章 · 获赞 86 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/unicorn97/article/details/102463153