Flutter - Package 简介
Dart 组织和共享一组功能的方式是通过 Package。Dart Package 只是可共享的库或模块。一般来说,Dart Package 与 Dart Application 相同,只是 Dart Package 没有应用程序入口点 main。
Package 的一般结构(考虑一个演示包,my_demo_package)如下 −
lib/src/* − 私有 Dart 代码文件。
lib/my_demo_package.dart − 主 Dart 代码文件。它可以作为 −
导入到应用程序中
import 'package:my_demo_package/my_demo_package.dart'
如有必要,可以将其他私有代码文件导出到主代码文件 (my_demo_package.dart),如下所示 −
export src/my_private_code.dart
lib/* − 以任何自定义文件夹结构排列的任意数量的 Dart 代码文件。代码可以这样访问,
import 'package:my_demo_package/custom_folder/custom_file.dart'
pubspec.yaml − 项目规范,与应用程序相同,
Package 中的所有 Dart 代码文件都只是 Dart 类,对于 Dart 代码将其包含在 Package 中没有任何特殊要求。
Package 的类型
由于 Dart Package 基本上是类似功能的小集合,因此可以根据其功能进行分类。
Dart Package
通用 Dart 代码,可用于 Web 和移动环境。例如,english_words 就是这样一个包,它包含大约 5000 个单词,并具有名词(列出英语名词)、音节(指定单词中的音节数)等基本实用功能。
Flutter 包
通用 Dart 代码,依赖于 Flutter 框架,只能在移动环境中使用。例如,fluro 是 Flutter 的自定义路由器。它依赖于 Flutter 框架。
Flutter 插件
通用 Dart 代码,依赖于 Flutter 框架以及底层平台代码(Android SDK 或 iOS SDK)。例如,camera 是一个与设备摄像头交互的插件。它依赖于 Flutter 框架以及底层框架来访问摄像头。
使用 Dart 包
Dart 包托管并发布到实时服务器中,https://pub.dartlang.org。此外,Flutter 提供了简单的工具 pub 来管理应用程序中的 Dart Packages。使用 Package 所需的步骤如下 −
将包名称和所需的版本包含到 pubspec.yaml 中,如下所示 −
dependencies: english_words: ^3.1.5
可以通过检查在线服务器找到最新版本号。
使用以下命令将软件包安装到应用程序中 −
flutter packages get
在 Android Studio 中开发时,Android Studio 会检测到 pubspec.yaml 中的任何更改,并向开发人员显示 Android Studio 软件包警报,如下所示 −
可以使用菜单选项在 Android Studio 中安装或更新 Dart 软件包。
使用下面显示的命令导入必要的文件并开始工作 −
import 'package:english_words/english_words.dart';
使用包中可用的任何方法,
nouns.take(50).forEach(print);
在这里,我们使用 nouns 函数来获取并打印前 50 个单词。
开发 Flutter 插件包
开发 Flutter 插件类似于开发 Dart 应用程序或 Dart 包。唯一的例外是插件将使用系统 API(Android 或 iOS)来获取所需的平台特定功能。
由于我们已经在前面的章节中学习了如何访问平台代码,让我们开发一个简单的插件 my_browser 来了解插件开发过程。 my_browser 插件的功能是允许应用程序在特定于平台的浏览器中打开给定的网站。
启动 Android Studio。
单击文件 → 新建 Flutter 项目并选择 Flutter 插件选项。
您可以看到 Flutter 插件选择窗口,如下所示 −
输入 my_browser 作为项目名称,然后单击 Next。
在窗口中输入插件名称和其他详细信息,如下所示 −
在下面显示的窗口中输入公司域名 flutterplugins.tutorialspoint.com,然后单击 Finish。它将生成一个启动代码来开发我们的新插件。
打开 my_browser.dart 文件并编写一个方法 openBrowser 来调用特定于平台的 openBrowser 方法。
Future<void> openBrowser(String urlString) async { try { final int result = await _channel.invokeMethod( 'openBrowser', <String, String>{ 'url': urlString } ); } on PlatformException catch (e) { // Unable to open the browser print(e); } }
打开 MyBrowserPlugin.java 文件并导入以下类 −
import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle;
在这里,我们必须导入从 Android 打开浏览器所需的库。
在 MyBrowserPlugin 类中添加新的 Registrar 类型的私有变量 mRegistrar。
private final Registrar mRegistrar;
在这里,Registrar 用于获取调用代码的上下文信息。
在 MyBrowserPlugin 类中添加一个构造函数来设置 Registrar。
private MyBrowserPlugin(Registrar registrar) { this.mRegistrar = registrar; }
更改 registerWith 以将我们的新构造函数包含在 MyBrowserPlugin 类中。
public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "my_browser"); MyBrowserPlugin instance = new MyBrowserPlugin(registrar); channel.setMethodCallHandler(instance); }
将 onMethodCall 更改为包含 MyBrowserPlugin 类中的 openBrowser 方法。
@Override public void onMethodCall(MethodCall call, Result result) { String url = call.argument("url"); if (call.method.equals("getPlatformVersion")) { result.success("Android " + android.os.Build.VERSION.RELEASE); } else if (call.method.equals("openBrowser")) { openBrowser(call, result, url); } else { result.notImplemented(); } }
在 MyBrowserPlugin 类中编写特定于平台的 openBrowser 方法来访问浏览器。
private void openBrowser(MethodCall call, Result result, String url) { Activity activity = mRegistrar.activity(); if (activity == null) { result.error("ACTIVITY_NOT_AVAILABLE", "Browser cannot be opened without foreground activity", null); return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); activity.startActivity(intent); result.success((Object) true); }
my_browser插件完整源代码如下 −
my_browser.dart
import 'dart:async'; import 'package:flutter/services.dart'; class MyBrowser { static const MethodChannel _channel = const MethodChannel('my_browser'); static Future<String> get platformVersion async { final String version = await _channel.invokeMethod('getPlatformVersion'); return version; } Future<void> openBrowser(String urlString) async { try { final int result = await _channel.invokeMethod( 'openBrowser', <String, String>{'url': urlString}); } on PlatformException catch (e) { // Unable to open the browser print(e); } } }
MyBrowserPlugin.java
package com.tutorialspoint.flutterplugins.my_browser; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry.Registrar; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; /** MyBrowserPlugin */ public class MyBrowserPlugin implements MethodCallHandler { private final Registrar mRegistrar; private MyBrowserPlugin(Registrar registrar) { this.mRegistrar = registrar; } /** Plugin registration. */ public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel( registrar.messenger(), "my_browser"); MyBrowserPlugin instance = new MyBrowserPlugin(registrar); channel.setMethodCallHandler(instance); } @Override public void onMethodCall(MethodCall call, Result result) { String url = call.argument("url"); if (call.method.equals("getPlatformVersion")) { result.success("Android " + android.os.Build.VERSION.RELEASE); } else if (call.method.equals("openBrowser")) { openBrowser(call, result, url); } else { result.notImplemented(); } } private void openBrowser(MethodCall call, Result result, String url) { Activity activity = mRegistrar.activity(); if (activity == null) { result.error("ACTIVITY_NOT_AVAILABLE", "Browser cannot be opened without foreground activity", null); return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); activity.startActivity(intent); result.success((Object) true); } }
创建一个新项目 my_browser_plugin_test 来测试我们新创建的插件。
打开 pubspec.yaml 并将 my_browser 设置为插件依赖项。
dependencies: flutter: sdk: flutter my_browser: path: ../my_browser
Android Studio 将提醒 pubspec.yaml 已更新,如以下 Android Studio 软件包警报中所示 −
单击获取依赖项选项。Android Studio 将从 Internet 获取软件包并为应用程序正确配置它。
打开 main.dart 并包含 my_browser 插件,如下所示 −
import 'package:my_browser/my_browser.dart';
从 my_browser 插件调用 openBrowser 函数,如下所示 −
onPressed: () => MyBrowser().openBrowser("https://flutter.dev"),
main.dart 的完整代码如下 −
import 'package:flutter/material.dart'; import 'package:my_browser/my_browser.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage( title: 'Flutter Demo Home Page' ), );, } } class MyHomePage extends StatelessWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(this.title), ), body: Center( child: RaisedButton( child: Text('Open Browser'), onPressed: () => MyBrowser().openBrowser("https://flutter.dev"), ), ), ); } }
运行应用程序并单击"打开浏览器"按钮,然后会看到浏览器已启动。您可以看到浏览器应用程序 - 主页,如下面的屏幕截图所示 −
您可以看到浏览器应用程序 - 浏览器屏幕,如下面的屏幕截图所示 −