Flutter原生方法通信插件action_channel的使用

Flutter原生方法通信插件action_channel的使用

概述

action_channel 插件是一个方便的功能包装器,它将一个 sink 和一个 stream 结合在一起。该插件允许输入/接收类型与输出/发送类型不同,并且可以处理回复,使其可用作请求-响应通道。

特性

  • 允许输入/接收类型与输出/发送类型不同,简化入口点。
  • 处理“回复”,使其可用作请求-响应通道。
  • 当接收到某些数据时,可以运行特定操作。

安装

pubspec.yaml 文件中添加依赖项:

dependencies:
  action_channel: ^x.x.x

然后在 Dart 文件中导入包:

import 'package:action_channel/action_channel.dart';

使用

创建通道

你可以通过 sink 和 stream 创建一个通道。你还可以指定一个动作,当调用 .on() 方法时,该动作会使用返回的数据执行。

final channel = Channel(
  sink, 
  stream,
  action: (String data) => print('Action using "$data"')
);

监听数据

你可以使用 .on() 方法监听通道,这将使你能够运行一个动作并使用返回的数据,就像一个“回复”。

final subscription = channel.on((data) {
  print('Data received "$data"');
  return 'New action using "$data"';
});

// 取消订阅
subscription.cancel();

你也可以使用 .once() 方法来监听通道仅一次。

channel.once((data) {
  print('First data: "$data"');
});

注意: 通道可以用作流,使用 .listen() 方法。

通道控制器

创建通道时可以使用 ChannelController,它自身处理 sink 和 stream 的创建,从而抽象出 sink 和 stream 的创建过程。控制器需要一个函数,该函数将输入/接收数据类型转换为输出/发送数据类型。

推荐使用 Channel.controller() 工厂方法,它会自动创建一个 ChannelController

final channel = Channel<int, String, void>.controller(
  (int id) => User(id),
);

// 带有回调的控制器
final channel = Channel<int, String, void>.controller(
  (int id) => User(id),
  
  onAdded: (int id) => print('User $id added'),
  onData: (User user) => print('User with id "${ user.id }" received'),
  onListen: (subscription) => print('Channel listened'),
  onClose: () => print('Channel closed'),
);

示例

以下是一个完整的示例,展示了如何使用 action_channel 插件。

import 'package:action_channel/action_channel.dart'; 

final users = <User>{
  User(1, 'John'),
  User(2, 'Tom', muted: true),
  User(3, 'Alex'),
};

void main() {
  final channel = Channel<int, User, String>.controller(
    (id) => users.firstWhere((user) => user.id == id),
    action: (message, user, channel) => user.say(message),
  );

  // 过滤非静音用户并监听数据
  channel.where((user) => !user.muted).on((user) => 'Hello!');

  // 监听一次数据
  channel.once((data) {
    print('First user: ${data.name}');
    return null;
  });

  // 添加用户
  channel.add(1);
  channel.add(2);
  channel.add(3);
}

/* -= Models =- */

class User {
  final int id;
  final String name;
  final bool muted;

  User(this.id, this.name, { this.muted = false });

  void say(String message) => print('User $id says "$message"');
}

更多关于Flutter原生方法通信插件action_channel的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter原生方法通信插件action_channel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用action_channel(通常指的是MethodChannel,因为Flutter并没有一个官方名为action_channel的插件,但概念上是类似的)进行原生方法通信的代码案例。

Flutter 端代码

首先,在你的Flutter项目中创建一个Dart文件来定义与原生平台通信的接口。假设我们创建一个名为platform_channel.dart的文件:

import 'package:flutter/services.dart';

class PlatformChannel {
  static const MethodChannel _channel = const MethodChannel('com.example.yourapp/platform_channel');

  static Future<String?> getPlatformVersion() async {
    final String? version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
}

然后,在你的Flutter组件中调用这个接口:

import 'package:flutter/material.dart';
import 'platform_channel.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Platform Channel Example'),
        ),
        body: Center(
          child: FutureBuilder<String?>(
            future: PlatformChannel.getPlatformVersion(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                }
                return Text('Platform Version: ${snapshot.data ?? 'Unknown'}');
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }
}

原生 Android 端代码

接下来,在你的Android项目中处理来自Flutter的调用。假设你的Flutter项目已经集成了Android平台。

MainActivity.kt(或MainActivity.java,如果你使用的是Java)中添加以下代码:

Kotlin 版本

package com.example.yourapp

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    private val CHANNEL = "com.example.yourapp/platform_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "getPlatformVersion") {
                result.success("Android ${android.os.Build.VERSION.RELEASE}")
            } else {
                result.notImplemented()
            }
        }
    }
}

Java 版本

package com.example.yourapp;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import android.os.Build;
import android.os.Bundle;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "com.example.yourapp/platform_channel";

    @Override
    public void configureFlutterEngine(FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler(
                        (call, result) -> {
                            if (call.method.equals("getPlatformVersion")) {
                                String platformVersion = "Android " + Build.VERSION.RELEASE;
                                result.success(platformVersion);
                            } else {
                                result.notImplemented();
                            }
                        }
                );
    }
}

原生 iOS 端代码

最后,在你的iOS项目中处理来自Flutter的调用。假设你的Flutter项目已经集成了iOS平台。

AppDelegate.swift中添加以下代码:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(name: "com.example.yourapp/platform_channel", binaryMessenger: controller)
    channel.setMethodCallHandler({
      (call: FlutterMethodCall, result: @escaping FlutterResult) in
      if call.method == "getPlatformVersion" {
        let version = UIDevice.current.systemVersion
        result(version)
      } else {
        result(FlutterMethodNotImplemented)
      }
    })
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

这就是一个完整的示例,展示了如何在Flutter与原生平台(Android和iOS)之间通过MethodChannel进行通信。你可以根据需要扩展这个示例来处理更多的方法调用和数据传输。

回到顶部