首页 > 解决方案 > Flutter 的 `dart:ui` 库中的 `PluginUtilities` 有什么作用,我该如何使用它?

问题描述

PluginUtilities被记录为“Flutter 插件作者的功能”。很难理解它的作用。我应该何时/如何使用它?

标签: flutter-plugin

解决方案


PluginUtilities做两件事:

您可以在运行不同代码的完全不同的隔离之间传递这些引用。例如,您可以在 Isolate A 中实现一个方法,获取它的句柄,将句柄传递给 Isolate B,使用PluginUtilities.getCallbackHandle从该句柄中获取方法,然后在 Isolate B 中调用该方法。

final handle = PluginUtilities.getCallbackHandle(myLovelyFunctionTearOff); // What is a tear off?: https://stackoverflow.com/questions/69065771/what-is-an-instance-method-tear-off
if (handle == null) {
  // function has to be a static method or a top level function. It is null otherwise.
  // TODO Show an error to the user to help them fix it.
}

在单独的隔离中收到句柄后,您可以再次获取该函数:

final function = PluginUtilities.getCallbackFromHandle(handle);
final result = function();

使用示例

Firebase 消息使用它两次,特别是用于后台消息。他们将其用于 2 个功能:

  • 他们获得用户设置的用户回调函数的句柄。
    • final CallbackHandle userHandle = PluginUtilities.getCallbackHandle(handler)!;
  • 他们获得了附加应用入口点的句柄(main他们调用的函数_firebaseMessagingCallbackDispatcher ):
    • final CallbackHandle bgHandle = PluginUtilities.getCallbackHandle(_firebaseMessagingCallbackDispatcher)!;

他们将这些句柄保存到 SharedPreferences 中,并在应用程序通过推送通知启动时使用它们。这是因为在这种情况下,Flutter 应用程序不会在 Android 上自动启动。服务或广播接收器在没有 Activity 的情况下启动,它会启动 FlutterEngine 和您的应用程序

发生这种情况时,Firebase_messaging将使用这些句柄获取回调函数和应用程序入口点,并启动它们。因此,当您的应用程序未运行时,您的回调仍然会被调用,因为它运行一个新的应用程序/入口点( _firebaseMessagingCallbackDispatcher):

void _firebaseMessagingCallbackDispatcher() {
  // Initialize state necessary for MethodChannels.
  WidgetsFlutterBinding.ensureInitialized();

  const MethodChannel _channel = MethodChannel(
    'plugins.flutter.io/firebase_messaging_background',
  );

  // This is where we handle background events from the native portion of the plugin.
  _channel.setMethodCallHandler((MethodCall call) async {
     /** implementation of method call handling **/
  });

  // Once we've finished initializing, let the native portion of the plugin
  // know that it can start scheduling alarms.
  _channel.invokeMethod<void>('MessagingBackground#initialized');

推荐阅读