您当前的位置: 首页 >  flutter

Kevin-Dev

暂无认证

  • 0浏览

    0关注

    544博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Flutter -- 进阶】Packages

Kevin-Dev 发布时间:2022-07-26 08:00:00 ,浏览量:0

在这里插入图片描述

文章目录
    • 1. 简介
    • 2. Package 类型
    • 3. 包的使用
    • 4. 开发插件包(plugin package)
      • 4.1 实现MethodCallHandler接口
      • 4.2 完善onMethodCall方法
      • 4.3 Flutter客户端
      • 4.4 使用插件
      • 4.5 发布插件

1. 简介

用过Flutter的开发者都知道,Flutter的库是以包(package)的方式来管理,使用package可以创建可轻松共享的模块化代码。一个最小的package包括:

  • 一个pubspec.yaml文件:声明了package的名称、版本、作者等的元数据文件
  • 一个lib文件夹:包括包中公开的(public)代码,最少应有一个.dart文件
2. Package 类型

Packages可以包含多种内容:

  • Dart包(library package):其中包含一些Flutter特定功能,因此对Flutter框架具有依赖性,仅将用于Flutter,例如Fluro包,也就是我们平常说的Flutter包。
  • 插件包(plugin package):当我们说Flutter插件的时候就是指这,一种专用的Dart包,其中包含用Dart代码编写的API,以及针对Android(使用Java或者Kotlin)和/或针对iOS(使用Object-C或者Swift)平台的特定实现,一个具体例子就是battery插件包。
3. 包的使用

我们在平时中经常使用库,流程是在pubspec.yaml里声明一个依赖:

  path_provider: ^0.4.1
  cached_network_image: ^0.5.0+1

这里简单说明一下,之前没有讲解,后来查了一下,^x.x.x 这个是库对应的版本号,^0.4.1表示和0.4.1版本兼容,也可以指定特定的版本:

  • 0.4.1:特定的版本
  • any:任意版本
  • 0.4.1:大于0.4.1的版本
  • =0.4.1:大于等于0.4.1的版本
  • >=0.4.1 New > New FLutter Project
  • 在目录面板中选择第二个Flutter Plugin,点击nextAndroid stdio 会有显示Select "plugin" when exposing an Android or iOS API for develops
  • Project name填写knight_toast_plugin,这个名字随意,但是要防止和pub上的库名字冲突
  • 看看项目的目录: 在这里插入图片描述 主要看四个目录就可以了:

    • android:插件包API的Android端实现
    • example:一个依赖该插件的Flutter应用程序,来说明如何使用它
    • ios:插件包API的iOS端实现
    • lib:Dart包的API,插件的客户端会使用这里实现的接口

    项目创建就是一个完整的简单插件例子,这个例子是实现了platformVersion。把android目录打开:

    /** KnightToastPlugin */
    public class KnightToastPlugin implements MethodCallHandler {
      /** Plugin registration. */
      public static void registerWith(Registrar registrar) {
        final MethodChannel channel = new MethodChannel(registrar.messenger(), "knight_toast_plugin");
        channel.setMethodCallHandler(new KnightToastPlugin());
      }
    
      @Override
      public void onMethodCall(MethodCall call, Result result) {
        if (call.method.equals("getPlatformVersion")) {
          result.success("Android " + android.os.Build.VERSION.RELEASE);
        } else {
          result.notImplemented();
        }
      }
    }
    

    发现和一开始使用平台通道编写平台特定的代码很像,从上面知道knightToastPlugin这个插件实现了MethodCallHandler,先看看这个MethodCallHandler接口:

        //返回结果接口
        public interface Result {
            //成功
            void success(@Nullable Object var1);
            //失败
            void error(String var1, @Nullable String var2, @Nullable Object var3);
            //没有实现接口时回调 通常是调用了未知的方方法
            void notImplemented();
        }
        //处理本地方法的请求接口
        public interface MethodCallHandler {
            void onMethodCall(MethodCall var1, MethodChannel.Result var2);
        }
    

    反正实现一个插件时需要实现这个接口,下面实现弹出吐司这个功能:

    4.1 实现MethodCallHandler接口
    public class KnightToastPlugin implements MethodCallHandler{
    
      //插件注册
      public static void registerWith(Registrar registrar){
        //samples.flutter/knight_toast_plugin 这是Method channel的名字 上面是有说过,这里并且添加了域名,为了防止冲突
        final MethodChannel channel = new MethodChannel(registrar.messenger(), "samples.flutter/knight_toast_plugin");
        channel.setMethodCallHandler(new KnightToastPlugin());
    
      }
    
      @Override
      public void onMethodCall(MethodCall methodCall, Result result) {
    
      }
    }
    

    因为使用过Toast都知道,Android需要一个上下文环境(Context),把Context参数加上:

      private Context mContext;
      public KnightToastPlugin(Context mContext){
        this.mContext = mContext;
      }
      //插件注册
      public static void registerWith(Registrar registrar){
        ....
        //从Registrar获得context
        channel.setMethodCallHandler(new KnightToastPlugin(registrar.context()));
    
      }
    
    4.2 完善onMethodCall方法
      @Override
      public void onMethodCall(MethodCall methodCall, Result result) {
         //首先判断方法名是否为"showToast"
         if(methodCall.method.equals("showToast")){
            //因为调用原生,只能传递一个参数,如果想要传递多个,那就放在map里,用map传递
            //用MethodCall.argument("xxxx")来取值
            //显示内容
            String message = methodCall.argument("message");
            //时间为short 还是 long
            String duration = methodCall.argument("duration");
            //调用原生弹出吐司
            Toast.makeText(mContext,message,duration.equals("length_short") ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show;
            //成功
            result.success(true); 
         } else {
            //没这个方法
            result.notImplemented(); 
         }
      }
    
    4.3 Flutter客户端

    在 FLutter 客户端需要做有两步:

    • 生成一个MethodChannel,例子已经帮生成了。
    • 通过这个MethodChannel调用showToast方法。

    在这里插入图片描述

    import 'dart:async';
    import 'package:flutter/services.dart';
    
    
    enum Duration{
      length_short,
      length_long
    }
    
    class KnightToastPlugin {
      //这里要和你在android目录下写的插件通道要对应 new MethodChannel(registrar.messenger(), "samples.flutter/knight_toast_plugin");
      static const MethodChannel _channel =
          const MethodChannel('samples.flutter/knight_toast_plugin');
    //  不需要自带的例子
    //  static Future get platformVersion async {
    //    final String version = await _channel.invokeMethod('getPlatformVersion');
    //    return version;
    //  }
      static Future showToast(String message,Duration duration) async{
        //参数封装
        var argument = {'message':message,'duration':duration.toString()};
        //这个方法是异步调用 "showToast"对应在上面所写的原生代码的methodCall.method.equals("showToast")
        var success = await _channel.invokeMethod('showToast',argument);
        return success;
      }
    }
    
    
    4.4 使用插件

    example > lib目录下的main.dart修改如下:

    import 'package:flutter/material.dart';
    import 'package:knight_toast_plugin/knight_toast_plugin.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State {
      _showToast(){
        KnightToastPlugin.showToast("吐司出来~", Duration.length_short);
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Plugin example app'),
            ),
            body: Center(
              child: Text('吐司例子'),
            ),
            floatingActionButton : FloatingActionButton(
                onPressed: _showToast,
                tooltip: "可以弹出toast",
                child: new Icon(Icons.audiotrack)
            ),
          ),
        );
      }
    }
    

    效果如下: 在这里插入图片描述

    4.5 发布插件

    插件功能做出来,下面就等发布了,下面把插件发布到pub.dartlang.org上,发布需要科学上网。。,检查pubspec.yaml,这里需要补一下基本信息:

    name: knight_toast_plugin ->插件名字

    description: toast_plugin ->插件描述

    version: 0.0.1 ->插件版本

    author: kevin0724@163.com ->作者

    homepage: https://github.com/KnightAndroid->主页

    建议将下面文档添加到插件包:

    • README.md:结束插件的文件
    • CHANGELOG:记录每个版本中的更改
    • LICENSE:包含插件许可条款的文件 在这里插入图片描述

    检查插件,在根目录执行下面命令,检测插件有没有问题:

    flutter packages pub publish --dry-run
    

    如果显示包太大,就把build、.idea删除,并且把一些警告解决,最后输出:

    Package has 0 warnings.
    

    下面就可以真正发布插件了,命令如下:

    flutter packages pub publish
    
关注
打赏
1658837700
查看更多评论
立即登录/注册

微信扫码登录

0.0398s