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

今天来学习Flutter的一些高级技巧,在实际工作中也是要用得上的,比如如何将咱们的代码发布到https://pub.dev/上造轮子给全球使用,在Flutter中如何调Android和Ios本地代码,以及Android中如何来调Flutter【由于ios我不会,所以。。】,内容还是很刺激的,下面开始搞起。

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_第1张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第2张图片

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

项目创建:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第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_第4张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第5张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第6张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第7张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第8张图片

代码编写:

效果:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第9张图片

其实用到的知识点在https://www.cnblogs.com/webor2006/p/12649906.html已经学习过了,是啥呢?

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第10张图片

具体实现:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第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: [
      ],
    );
  }
}

接下来则来定义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: [
        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_第12张图片

其作用是:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第13张图片

创建示例工程:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第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/[email protected] (created)
  example/ios/Runner/Assets.xcassets/LaunchImage.imageset/[email protected] (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/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (created)
  example/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected] (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_第15张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第16张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第17张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第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 {
  @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_第19张图片

直接右键运行一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第20张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第21张图片

嗯,没啥问题。

发布【比较曲折】:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第22张图片 

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第23张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第24张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第25张图片

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第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_第27张图片

然后添加到本地仓库中:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第28张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第29张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第30张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第31张图片 

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第32张图片

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第33张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第34张图片 

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第35张图片 

试一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第36张图片 

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第37张图片 

发现需要授权。。

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_第38张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第39张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第40张图片

啥情况呢,网上搜了一下,按这博主https://blog.csdn.net/perfectnihil/article/details/103366428的意思貌似是要FQ。。正好我也有梯子,那试一下呗:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第41张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第42张图片

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第43张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第44张图片

这时因为咱们在Flutter学习环境搭建的时候设置了中国的镜像,为了学习顺畅嘛,身为国人都懂的,回忆一下https://www.cnblogs.com/webor2006/p/11367345.html: 

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第45张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第46张图片

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

那咱们改一下名称:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第47张图片

当然example也得改一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第48张图片

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第49张图片

再来:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第50张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第51张图片 

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第52张图片

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

Flutter Plugin:

了解:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第53张图片

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

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第54张图片

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

项目创建:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第55张图片

咱们试一下:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第56张图片

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

此时咱们用IDE打开它:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第57张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第58张图片

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

分析官方DEMO流程:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第59张图片

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

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 {
  String _platformVersion = 'Unknown';

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

  // Platform messages are asynchronous, so we initialize in an async method.
  Future 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_第60张图片

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第61张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第62张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第63张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第64张图片

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

模仿编写自己的插件:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第65张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第66张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第67张图片 
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_第68张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第69张图片

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

Flutter Module:

了解:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第70张图片

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

第一步:创建Android工程

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第71张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第72张图片

第二步:创建Flutter工程:

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第73张图片

此时的目录结构为:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第74张图片

第二步:编译Flutter工程

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第75张图片

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

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

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第76张图片 

2、修改app下的build.gradle:

增加flutter的模块依赖:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第77张图片

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

怎么创建呢?看代码:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第78张图片

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第79张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第80张图片 

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第81张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第82张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第83张图片

那现在已经在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_第84张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第85张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第86张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第87张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第88张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第89张图片

再运行:

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第90张图片

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

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

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

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第91张图片

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

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

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第92张图片

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

Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module_第93张图片

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

你可能感兴趣的:(flutter学习,android,java,dart,app,android,studio)