美文网首页Flutter学习分享-齐绪东
Flutter 插件 Federated plugins

Flutter 插件 Federated plugins

作者: 外星间谍 | 来源:发表于2020-05-17 15:23 被阅读0次

    2020-05-15 12:19:39
    Federated plugins

    Federated plugins

    插件 2.0 还提出了 federated plugins 的概念。
    官网的大致意思是:
    在这之前,一个插件中包含了 Dart 代码,Android 平台代码 和 iOS 平台代码,他们都在一个包中。
    federated plugins 的目的是把他们分离成独立的包。

    需要3种类型的包:

    • platform interface package
      各平台需要提供的功能,都以接口的形式声明在了这个包中。
    • platform package(s)
      特定平台实现接口的包。可以有多个,比如一个用于 Web ,一个用于 Mac OS 。
    • app-facing package
      是给使用插件的人用的。插件为 app 提供的各种功能在这个包中,插件使用者调用这个包中的方法。
      接口为这个包提供一个平台的实现,这个包调用实现中的方法。

    使用一个插件,直接用到的就是 app-facing package 。

    官网给出了一个 Medium 上的文章 How To Write a Flutter Web Plugin, Part 2
    但是不太容易看懂,可以先看另一篇。Modern Flutter Plugin Development

    文章中反复强调实现接口的时候要用 extends ,不要用 implements 。

    虽然官方提出了这个东西,但是官方插件中的安卓和 iOS 代码还是写在老地方。
    因为 federated plugins 的出现,主要是方便为安卓和 iOS 之外的平台添加支持,
    比如 Web 和 Mac OS 。
    不过挺多插件已经把接口分离出来了。

    我的演示

    如果把插件示例改成 federated plugins 的话。
    可以先简单点。直接在同一个位置放3个文件就好了。

    /// 文件 platform_interface.dart
    /// 相当于 platform interface package
    
    import 'platform_channel.dart';
    
    abstract class DemoInterface {
    
      static DemoInterface instance = DemoChannel();
    
      Future<String> get platformVersion {
        throw UnimplementedError('platformVersion has not been implemented.');
      }
    }
    
    /// 文件 platform_channel.dart
    /// 相当于 platform package
    
    import 'package:flutter/services.dart';
    
    import 'platform_interface.dart';
    
    const MethodChannel _channel = const MethodChannel('platform_channel');
    
    class DemoChannel extends DemoInterface {
    
      static void register() {
        DemoInterface.instance = DemoChannel();
      }
    
      @override
      Future<String> get platformVersion async {
        final String version = await _channel.invokeMethod('getPlatformVersion');
        return version;
      }
    }
    
    /// 文件 federated_plugin_demo.dart
    /// 相当于 app-facing package
    
    import 'dart:async';
    
    import 'platform_interface.dart';
    
    class DemoPlugin {
    
      static Future<String> get platformVersion async {
        final String version = await DemoInterface.instance.platformVersion;
        return version;
      }
    }
    
    /// 在 Flutter app 中的使用
    import 'dart:async';
    
    import 'federated_plugin_demo.dart';
    
    Future<void> foo() async {
      String platformVersion = await DemoPlugin.platformVersion;
    }
    

    platform package 实现了接口。
    app-facing package 通过接口类的静态成员 instance 得到接口类的实现,
    然后就可以调用接口中的方法。

    接口中的静态成员 instance 。

    当前 app 运行在哪个平台,就会把它设置成哪个平台的实现。
    例如通过 DemoChannel 中的 register() 方法进行设置。
    这样 “app-facing package” 就可以调用那个特定平台中的实现了。

    上面的例子把 instance 初始化了一个需要 MethodChannel 才能与特定平台通信的实例。
    这个初始化其实算是设置了一个默认值。

    复杂点的例子

    码云地址

    这个例子也就是把上面的例子放在不同的包中。

    我这个例子和官方做法不太一样,
    是3个独立的包,放在了另一个包中。
    最外层的包,是 “app-facing package” ,
    里面放了

    • platform interface package 是接口
    • platform channel 作为 “platform package”,这个包中有Android 和 iOS 平台代码。
    • platform register 用来设置接口中的 instance 。

    官方的做法是把 “app-facing package” 和 Android,iOS原生平台代码放一起了。
    我觉得 channel 算是 “platform package”,
    官方把它和 “platform interface package” 放一起了。

    官方的做法感觉逻辑比较混乱,我就尝试分开下,加深理解。
    要注意 pubspec 文件的使用。
    另外我写了一个 “platform register”,
    感觉这个应该可以由编译器实现,为哪个平台编译,就把 instance 设置成对应平台的实现。

    虽然感觉官方的做法不太符合逻辑,
    但是实际写插件的话,还是按照官方的写法比较简单。

    相关文章

    1. 【Flutter】从启动到插件开始执行

    参考资料

    相关文章

      网友评论

        本文标题:Flutter 插件 Federated plugins

        本文链接:https://www.haomeiwen.com/subject/yllsohtx.html