Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module

admin2024-10-07  24

Flutter Package:

关于这块的开发可以参考​​https://flutterchina.club/developing-packages/​​,下面则来从0开始来构建一款自己的Flutter包发布到Flutter Package上面。

了解:

关于Flutter Package是啥应该不用过多再解释了,如果说你想在​​https://pub.dev/​​发布自己写的库供别人来使用,此时就需要学会Flutter Package的技法了,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico,第1张

,这里贴一下网上所说有:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_02,第2张

其中上面说到Package类型有两种,而这里首先实现的是第一种:Dart包。

项目创建:

咱们先来新建一个Flutter工程,可以采用命令来进行创建,如网上所示:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_03,第3张

来吧,试一下:

bogon:workspace xiongwei$ cd flutterstudy/
bogon:flutterstudy xiongwei$ flutter create --template=package shaded_text
Creating project shaded_text...
shaded_text/LICENSE (created)
shaded_text/test/shaded_text_test.dart (created)
shaded_text/shaded_text.iml (created)
shaded_text/.gitignore (created)
shaded_text/.metadata (created)
shaded_text/pubspec.yaml (created)
shaded_text/README.md (created)
shaded_text/lib/shaded_text.dart (created)
shaded_text/.idea/libraries/Dart_SDK.xml (created)
shaded_text/.idea/modules.xml (created)
shaded_text/.idea/workspace.xml (created)
shaded_text/CHANGELOG.md (created)
Running "flutter packages get" in shaded_text... 1.2s
Wrote 12 files.

All done!
Your package code is in shaded_text/lib/shaded_text.dart
bogon:flutterstudy xiongwei$

此时在本地生成的样子瞅一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_04,第4张

当然还可以利用Android Studio的向导来创建:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_05,第5张

创建之后在Android Studio中咱们来看一下这个跟咱们正常的Flutter Application有啥不一样呢?

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_06,第6张

然后再看一下yaml配置文件:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_07,第7张

而且还有一个区别,就是此项目貌似没法运行:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_08,第8张

代码编写:

效果:

咱们这个包是要实现一个啥效果呢,其实比较简单,就是一个文本阴影的效果,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_09,第9张

其实用到的知识点在​​​​已经学习过了,是啥呢?

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_10,第10张

具体实现:

下面则来实现一下,定义一个Widget:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_11,第11张

然后具体的实现相对比较简单,就不一一说明了,重点是学会如何进行发布,实现如下,先定义相关的成员变量:

library shaded_text;

import 'package:flutter/material.dart';

class ShadedText extends StatelessWidget {
final String text;
final Color textColor;
final Color shadeColor;
final double xTans;
final double yTans;

ShadedText(
{this.text, this.textColor, this.shadeColor, this.xTans, this.yTans})
: assert(text != null),
assert(textColor != null),
assert(shadeColor != null);

@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
],
);
}
}

接下来则来定义Stack中的元素,这里就跟咱们之前写项目的时候不太一样了,因为这个库最终是要供别人来使用的,所以此时只需提供一个创建的行为,具体创建的细节由调用者来提供,啥意思呢?下面看一下代码体会一下:

library shaded_text;

import 'package:flutter/material.dart';

typedef ShadeBuilder = Widget Function(
BuildContext context, String text, Color);

class ShadedText extends StatelessWidget {
final String text;
final Color textColor;
final Color shadeColor;
final double xTans;
final double yTans;
final ShadeBuilder shadeBuilder;

ShadedText(
{this.text,
this.textColor,
this.shadeColor,
this.xTans,
this.yTans,
this.shadeBuilder})
: assert(text != null),
assert(textColor != null),
assert(shadeColor != null),
assert(shadeBuilder != null);

@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
shadeBuilder(context, text, textColor),
Transform(
transform:
Matrix4.translationValues(xTans ?? 10.0, yTans ?? 10.0, 0.0),
child: shadeBuilder(context, text, shadeColor),
),
],
);
}
}

其中有一个小小的Dart语法复习一下,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_12,第12张

其作用是:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_13,第13张

创建示例工程:

通常在发布的时候得给用户一个示例代码,所以此时咱们针对咱们所写的功能进行一下调用,正好可以测一下是否写得有问题,怎么创建呢?直接在Android Studio的Terminal来创建,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_14,第14张

bogon:shaded_text xiongwei$ flutter create example
Creating project example...
example/ios/Runner.xcworkspace/contents.xcworkspacedata (created)
example/ios/Runner/Info.plist (created)
example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png (created)
example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png (created)
example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md (created)
example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (created)
example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (created)
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (created)
example/ios/Runner/Base.lproj/LaunchScreen.storyboard (created)
example/ios/Runner/Base.lproj/Main.storyboard (created)
example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (created)
example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (created)
example/ios/Flutter/Debug.xcconfig (created)
example/ios/Flutter/Release.xcconfig (created)
example/ios/Flutter/AppFrameworkInfo.plist (created)
example/test/widget_test.dart (created)
example/example.iml (created)
example/.gitignore (created)
example/.metadata (created)
example/ios/Runner/AppDelegate.h (created)
example/ios/Runner/main.m (created)
example/ios/Runner/AppDelegate.m (created)
example/ios/Runner.xcodeproj/project.pbxproj (created)
example/android/app/src/profile/AndroidManifest.xml (created)
example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png (created)
example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png (created)
example/android/app/src/main/res/drawable/launch_background.xml (created)
example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (created)
example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (created)
example/android/app/src/main/res/values/styles.xml (created)
example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (created)
example/android/app/src/main/AndroidManifest.xml (created)
example/android/app/src/debug/AndroidManifest.xml (created)
example/android/gradle/wrapper/gradle-wrapper.properties (created)
example/android/gradle.properties (created)
example/android/settings.gradle (created)
example/pubspec.yaml (created)
example/README.md (created)
example/lib/main.dart (created)
example/android/app/build.gradle (created)
example/android/app/src/main/java/com/example/example/MainActivity.java (created)
example/android/build.gradle (created)
example/android/example_android.iml (created)
example/.idea/runConfigurations/main_dart.xml (created)
example/.idea/libraries/Flutter_for_Android.xml (created)
example/.idea/libraries/Dart_SDK.xml (created)
example/.idea/libraries/KotlinJavaRuntime.xml (created)
example/.idea/modules.xml (created)
example/.idea/workspace.xml (created)
Running "flutter packages get" in example... 1.7s
Wrote 66 files.

All done!
[!] Flutter is partially installed; more components are available. (Channel stable, v1.2.1, on Mac OS X 10.15.6 19G73, locale zh-Hans-CN)
[!] Android toolchain - develop for Android devices is partially installed; more components are available. (Android SDK version 29.0.3)
[!] iOS toolchain - develop for iOS devices is partially installed; more components are available. (Xcode 11.2.1)
[!] Android Studio is not available. (not installed)
[!] IntelliJ IDEA Ultimate Edition is partially installed; more components are available. (version 2020.2)
[!] Connected device is not available.

Run "flutter doctor" for information about installing additional components.

In order to run your application, type:

$ cd example
$ flutter run

Your application code is in example/lib/main.dart.

bogon:shaded_text xiongwei$

此时在工程中就可以看到咱们创建的Flutter项目了,也就是之前咱们学习Flutter所用的命令,当时此时是可以运行的喽,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_15,第15张

此时咱们来调用一下咱们写的插件,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_16,第16张

接下来需要使用咱们自己写的插件,怎么用呢?其实跟我们在之前做项目使用三方库一样,需要到yaml文件中进行引用,但是咱们的库还木有往外正式发布,所以使用上略有不同,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_17,第17张

其中这个"shaded_text"名称是你插件中这块的名称:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_18,第18张

接下来则可以来使用了:

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

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Shaded Text Demo'),
),
body: Center(
child: ShadedText(
text: 'Shaded Text',
textColor: Color(0xffff0000),
shadeColor: Color(0xff00ff00),
shadeBuilder: (BuildContext context, String text, Color color) =>
Container(
child: Text(
text,
style: TextStyle(color: color),
),
),
),
),
);
}
}

可以看到builder的使用方式跟我们之前在做项目时使用了大量这种方式类似,顺间领悟到了原来我们调用的内部机理,接下来运行看一下效果:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_19,第19张

直接右键运行一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_20,第20张

之后就可以看到运行的按钮可用了,效果如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_21,第21张

嗯,没啥问题。

发布【比较曲折】:

接下来则到激动人心的时刻了,准备将咱们写的高大上的DEMO给发布到Flutter的​​https://pub.dev/​​上去,能成功么?下面按照文档上的来:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_22,第22张 

此时咱们先运行dry-run来检查一下发布准备是否一切都ok:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_23,第23张

然后在最后给出了一个错误提示了:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_24,第24张

也就是这块配置文件中的这些信息得填一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_25,第25张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_26,第26张

还有最后一个异常需要处理:“

Your package is 146.1 MB. Hosted packages must be smaller than 100 MB. Your .gitignore has no effect since your project does not appear to be in version control.

Sorry, your package is missing some requirements and can't be published yet.

包太大了。。怎么办,其实上面中也有一个提示,说没有受版本的控制,那咱们将它加入到git仓库管理中试一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_27,第27张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_28,第28张

然后添加到本地仓库中:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_29,第29张

此时再来dry-run检测一次:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_30,第30张

 居然名字后面得跟一个邮件。。好吧,改!!

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_31,第31张

然后这里还可以修改一下CHANGLOG.md文件:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_32,第32张 

另外LICENSE也可以加一下,在github中的开源项目中随便找一个:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_33,第33张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_34,第34张

好,此时第三次再来dry-run:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_35,第35张 

完美了,接下来尝试发布,啥命令来着:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_36,第36张 

试一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_37,第37张 

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_38,第38张 

发现需要授权。。

Looks great! Are you ready to upload your package (y/n)? y
Pub needs your authorization to upload packages on your behalf.
In a web browser, go to https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&response_type=code&client_id=818368855108-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A56482&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email
Then click "Allow access".

Waiting for your authorization...

此时点击它提示的链接进行GOOGLE账号授权一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_39,第39张

接下来在Android Studio的发布命令台上就会收到授权成功的消息了,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_40,第40张

然后。。无限在处理中了。。然后最后收到这样的消息:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_41,第41张

啥情况呢,网上搜了一下,按这博主的意思貌似是要FQ。。正好我也有梯子,那试一下呗:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_42,第42张

这个错误没了,另一个失败又出现了,而且此时只明一个错误码出现没报具体原因。。网上继续搜,博主​​​​的意思是用-v来查看一下具体的异常:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_43,第43张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_44,第44张

输出日志往前看,发现用了cn中国的域名。。

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_45,第45张

这时因为咱们在Flutter学习环境搭建的时候设置了中国的镜像,为了学习顺畅嘛,身为国人都懂的,回忆一下​​​​​: Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_46,第46张

所以咱们在发布的时候先将这个镜像去掉,最终官网是在国外嘛:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_47,第47张

先注释掉,等发布成功了到时再还原,再来发布一次,注意:此时先得重启一下Android Studio再发布,不然咱们注释掉的环境变量没有生效,然后再设置一下之前的代理再发布:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_48,第48张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_49,第49张

那咱们改一下名称:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_50,第50张

当然example也得改一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_51,第51张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_52,第52张

再来:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_53,第53张

终于成功了。。咱们上官网搜一下能否搜到:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_54,第54张 

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_55,第55张

最后再将Flutter的国内镜像配置给还原。

Flutter Plugin:

了解:

 接下来学习另一种使用场景,也就是咱们在新建项目向导中的看到的它:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_56,第56张

看一下网上对这个插件的解释:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_57,第57张

这里再来看一下网上的一个示意图:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_58,第58张

其中可以看到Flutter能调用特定平台(android或ios),并且特定平台(android或ios)又调调用Flutter,达到一个互通的效果,当然目前咱们这里先只观注前者,后者在之后也会学习到,在了解了Flutter Plugin它的使用意义之后,接下来咱们则来开始实现咱们的第一个插件。

项目创建:

这里既可以使用Android Studio的向导来创建,也可以使用命令来创建,这里咱们用命令:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_59,第59张

咱们试一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_60,第60张

此时本地就创建了一个flutter_toast插件项目了:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_61,第61张

此时咱们用IDE打开它:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_62,第62张

然后咱们运行看一下默认的效果:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_63,第63张

显示出了当前平台的版本号。

分析官方DEMO流程:

接下来咱们来简单分析一下这个默认插件的生成,搞清楚了它,基本上也就掌握了自己来写插件的思路了,从Flutter本身分析起:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_64,第64张

先贴一下全局代码,如今学到这看这样的代码就变得很亲切了:

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

import 'package:flutter/services.dart';
import 'package:flutter_toast/flutter_toast.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';

@override
void initState() {
super.initState();
initPlatformState();
}

// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await FlutterToast.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}

// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;

setState(() {
_platformVersion = platformVersion;
});
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Text('Running on: $_platformVersion\n'),
),
),
);
}
}

简单撸一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_65,第65张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_66,第66张

接下来来看一下插件中是如何来获取指定平台的版本号的?

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_67,第67张

而最终方法的实现则是由具体的平台来执行的,所以咱们来看一下android平台是怎么来实现这个Flutter调用的指令的:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_68,第68张

此时在Flutter页面就可以看到方法的结果了,再看一下ios平台的写法,基本雷同,只是语法的不同:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_69,第69张

以上就是整个插件的使用流程。

模仿编写自己的插件:

接下来咱们依照官方的DEMO来改造第一个自己的插件,这个插件的功能就是弹个Toast出来,下面开始:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_70,第70张

此时则在插件中增加一个showToast的方法:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_71,第71张

接下来则在平台中来实现showToast的实现逻辑,这里以Android平台为例(ios目前还不会),如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_72,第72张 

package com.example.plugin.flutter_toast;

import android.content.Context;
import android.widget.TextView;
import android.widget.Toast;

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;

/**
* FlutterToastPlugin
*/
public class FlutterToastPlugin implements MethodCallHandler {
private Toast toast;
private Context context;

private FlutterToastPlugin(Context context) {
this.context = context;
}

/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_toast");
channel.setMethodCallHandler(new FlutterToastPlugin(registrar.context()));
}

@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if (call.method.equals("showToast")) {
String msg = call.argument("msg");
String duration = call.argument("duration");//long or short
Number textColor = call.argument("textColor");
Number textSize = call.argument("textSize");

toast = Toast.makeText(context, "", Toast.LENGTH_SHORT);
//set text
if (msg != null) {
toast.setText(msg);
}
//set duration
if (duration != null && duration.equals("long")) {
toast.setDuration(Toast.LENGTH_LONG);
} else {
toast.setDuration(Toast.LENGTH_SHORT);
}
//set styles
TextView textView = (TextView) toast.getView().findViewById(android.R.id.message);
//set text color
if (textView != null) {
textView.setTextColor(textColor.intValue());
}
//set text size
if (textView != null) {
textView.setTextSize(textSize.floatValue());
}
toast.show();
} else {
result.notImplemented();
}
}
}

此时运行看一下,发现报错了。。

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_73,第73张

这种情况咋整?其实在未来Flutter的开发中也可能会遇到这种情况,重新卸载安装一次就可以了,下面看一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_74,第74张

最后插件的发布跟上面package的一样,这里就略过了。

Flutter Module:

了解:

最后还有一个咱们木有使用过,如创建向导中的这个:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_75,第75张

简单描述就是在Android或ios原生工程中集成Flutter,这样就可以在Android原生中使用Flutter中的特性了,比较最典型的一个热重载,下面则分步骤一点点来实现这样的效果,还是只以Android平台为例,木办法,Ios的技能木有get到。。

第一步:创建Android工程

这里新创建一个文件夹,将所有接下来要创建的工程都存放于此,便于统一管理,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_76,第76张

然后在这个目录下创建一个Android工程:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_77,第77张

第二步:创建Flutter工程:

在Android工程根目录的上一级目录创建Flutter工程,保证Flutter工程与Android工程在同一级。如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_78,第78张

此时的目录结构为:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_79,第79张

第二步:编译Flutter工程

此时打开咱们创建的Flutter工程,然后需要进行编译,如何搞呢?看下面:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_80,第80张

第三步:在Android工程中加入Flutter Module的依赖

接下来回到Android工程中添加Flutter Module的依赖:

1、修改Android项目根目录下的setting.gradle:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_81,第81张 

2、修改app下的build.gradle:

增加flutter的模块依赖:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_82,第82张

第四步:在Android工程中创建Flutter的View

怎么创建呢?看代码:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_83,第83张

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_84,第84张

居然Flutter中用的不是androidx。。那怎么办?改变support方式吧:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_85,第85张 

然后还有一个地方得修改一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_86,第86张

此时再导一下包就可以了:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_87,第87张

然后布局文件也得改一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_88,第88张

那现在已经在Android中内嵌了Flutter的视图了,那视图的内容怎么办呢?当然得由Flutter来提供了。

第五步:在Flutter工程中创建Widget

回到Flutter工程中来进行代码的编写:

import 'dart:ui';

import 'package:flutter/material.dart';

void main() => runApp(selectWidget(window.defaultRouteName));

Widget selectWidget(String routeName) {
switch (routeName) {
case 'r1'://根据路由的名字来
return MyFlutterView();
default:
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Text(
'Unknow Route!',
style: TextStyle(color: Color(0xffff0000)),
),
),
),
);
}
}

class MyFlutterView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Card(
color: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0))),
child: Text('My Flutter View'),
),
),
),
);
}
}

其中的路由名就是咱们在Android中添加的Flutter中的路由名,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_89,第89张

好,接下来就可以来到Android工程中直接运行看下效果了:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_90,第90张

提示ndk版本有问题,那下载一下,然后再来运行,依然报错了:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_91,第91张

居然最小只支持8.0。。那咱们改一下最小SDK的版本:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_92,第92张

再来运行,发现ndk库链接错误:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_93,第93张

这个解决起来比较简单,加一个cpu的类型既可,如下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_94,第94张

再运行:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_95,第95张

可以发现加载Flutter View会有一些延时,这个可能得从产品交互的角度来解决,加个loading啥的,至此Android中内嵌Flutter成功搞定。

第六步:让Flutter模块支持热加载

不过目前对于Flutter的热加载功能还不支持,那就发挥不出它的优势了,所以接下来加上热加载功能,也比较简单,如下:

1、首先在Flutter Module工程目录下执行flutter attach,开始监听flutter。

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_android_96,第96张

此时它就在等Android工程进行启动。

2、在Android工程中运行程序,运行成功后可以在终端输入小写r热加载,大写R热重启。

重启运行Android工程,此时在Flutter的attach命令行中就会给出如下提示了:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_flutter_97,第97张

接下来咱们就可以在Flutter Module中进行修改实时在Android项目中进行预览了,下面演示一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module,Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_ico_98,第98张

另外对于Fragment的使用也基本类似,这里就不演示了,至此对于Flutter的高级技法就已经学习完毕啦,这些待实际项目中再来进行实践,接下来打算开启一个全新的Flutter的项目操练,要想彻底掌握,别无它法,只能勤加练习~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!