Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

学习flutter

License

NotificationsYou must be signed in to change notification settings

JeremyLiao/flutter-learn

Repository files navigation

flutter学习笔记,持续更新

优秀的学习资料

  1. flutter官方文档
  2. flutter-study
  3. Dart官方文档
  4. Flutter中文网

现有Android工程接入flutter module

  • 在真实的项目中,我们基本上不会去做一个纯flutter项目,都是在现有的Android工程中拿一个模块来用flutter实现
  • flutter官方文档中提供的接入方式:Add Flutter to existing apps

新建Flutter module

  1. 用命令flutter create新建
$ flutter create -t module my_flutter
  1. 用Android Studio新建

Android Studio->File->New->New Flutter Project->Flutter Module

集成到现有工程

以module引用的方式集成

  1. 在host app's settings.gradle中添加
// MyApp/settings.gradleinclude ':app'                                     // assumed existing contentsetBinding(new Binding([gradle: this]))                                 // newevaluate(new File(                                                      // new  settingsDir.parentFile,                                               // new  'my_flutter/.android/include_flutter.groovy'                          // new))
  1. 在build.gradle中引用
dependencies {  implementation project(':flutter')}

以aar文件的方式集成

在Flutter module的.android目录中打包aar
$ cd .android/$ ./gradlew flutter:assembleDebug

有些时候会遇到问题,这个时候可以尝试在flutter module的根目录下执行:

$ flutter clean$ flutter run
引用这个aar

host端app目录下新建目录libs。

app下build.gradle中添加:

repositories {    flatDir {        dirs 'libs'    }}

添加dependencies:

implementation name: 'flutter-debug', ext: 'aar'

从flutter module中拷贝生成的aar到libs目录下。

rebuild,run

十有八九会crash并且报错:

A/flutter: [FATAL:flutter/fml/icu_util.cc(95)] Check failed: context->IsValid(). Must be able to initialize the ICU context. Tried: /data/user/0/com.example.androidwithflutter3/app_flutter/icudtl.datA/libc: Fatal signal 6 (SIGABRT), code -6 in tid 21199 (oidwithflutter3)

原因就是文件icudtl.dat没有引进来(不得不说,flutter坑真多),解决方法:

  1. 新建assets目录并把icudtl.dat拷进来,注意路径是:assets/flutter_shared/icudtl.dat
  2. 可以在flutter.jar中找到这个文件

关于这个坑更多的描述,参见:#18025

完成之后就可以run起来了。

以远程仓库aar的方式集成

  1. 在Flutter module的.android目录中打包aar并上传仓库
  2. 引用这个远程aar

宿主端调用

宿主端Android APP可以通过route的方式调用flutter module中的内容,例如,Android端可以新建一个Activity来承载flutter。

public class FlutterViewActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        View flutterView = Flutter.createView(                FlutterViewActivity.this,                getLifecycle(),                "route"        );        setContentView(flutterView);    }}

也可以通过Fragment的形式来承载flutter

public class FlutterFragmentActivity extends FragmentActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_fm);        getSupportFragmentManager()                .beginTransaction()                .add(R.id.fragment_container, Flutter.createFragment("route"))                .commit();    }}

在flutter module中,需要实现路由

void main() => runApp(_widgetForRoute(window.defaultRouteName));Widget _widgetForRoute(String route) {  switch (route) {    case 'demo_app':      return MyApp();    case 'version':      return VersionPage();    default:      return ErrorPage('Unknown route: $route');  }}

Flutter Plugin

关于这个主题的官方文档地址:Developing packages & plugins

Android Studio IDE下的File/New/New Flutter Project选项下自带了四种模板:

  • Flutter Application: Flutter应用
  • Flutter Plugin:Flutter插件
  • Flutter Package:纯Dart组件
  • Flutter Module:Flutter模块

Flutter Plugin提供Android或者iOS的底层封装,在Flutter层提供组件功能,使Flutter层可以较方便的调用Android或者IOS层提供的接口。很多平台相关性或者对于Flutter实现起来比较复杂的部分,都可以封装成Plugin。

Flutter Plugin通信的原理图如下:

image

Dart层和平台层(Android&IOS)通过MethodChannel实现通信和调用。

新建Flutter Plugin

在Android Studio IDE下的File/New/New Flutter Project选项下选择模板Flutter Plugin,就可以新建一个Flutter Plugin。

新建的Flutter Plugin有以下主要部分:

  • android:android侧的插件代码
  • ios:ios侧的插件代码
  • lib:插件Dart代码
  • pubspec.yaml:插件配置文件
  • example:使用插件的flutter示例工程

Plugin的平台侧分析

Android侧java层的Plugin实现类,都会继承MethodCallHandler接口,在方法onMethodCall中实现对flutter层调用的分发,如:

@Overridepublic void onMethodCall(MethodCall call, Result result) {    if (call.method.equals(GET_PLATFORM_VERSION)) {        result.success("Android " + android.os.Build.VERSION.RELEASE);    } else if (call.method.equals(GET_SDK_INT)) {        result.success("Android SDK: " + android.os.Build.VERSION.SDK_INT);    } else {        result.notImplemented();    }}

而这个插件类被注册并暴露给flutter层,则是通过一个static方法:

public static void registerWith(Registrar registrar) {    final MethodChannel channel = new MethodChannel(registrar.messenger(), PLUGIN_NAME);    channel.setMethodCallHandler(new FlutterPlugin());}

这个插件是什么时候被注册的呢,在插件调用示例的example flutter工程的MainActivity中,我们可以看到在onCreate有这样一行代码:

protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    GeneratedPluginRegistrant.registerWith(this);}

GeneratedPluginRegistrant类是自动生成的插件注册类:

public final class GeneratedPluginRegistrant {  public static void registerWith(PluginRegistry registry) {    if (alreadyRegisteredWith(registry)) {      return;    }    FlutterPlugin.registerWith(registry.registrarFor("com.jeremyliao.flutterplugin.FlutterPlugin"));  }  private static boolean alreadyRegisteredWith(PluginRegistry registry) {    final String key = GeneratedPluginRegistrant.class.getCanonicalName();    if (registry.hasPlugin(key)) {      return true;    }    registry.registrarFor(key);    return false;  }}

在此处完成了插件的注册。

Plugin的flutter侧分析

lib下的代码就是flutter侧的实现,比如demo中的这个flutter_plugin.dart,本质上就是把平台侧的接口重新封装了一下,提供给其他dart使用:

class FlutterPlugin {  static const MethodChannel _channel = const MethodChannel('flutter_plugin');  static Future<String> get platformVersion async {    final String version = await _channel.invokeMethod('getPlatformVersion');    return version;  }  static Future<String> get sdkInt async {    final String version = await _channel.invokeMethod('getSdkInt');    return version;  }}

发布

插件开发完毕,可以发布插件让其他人使用,在发布之前,确保pubspec.yaml,、README.md以及CHANGELOG.md文件的内容都正确填写完毕。可以通过dry-run命令来看准备是否就绪。

flutter packages pub publish --dry-run

检查无误后,可以执行下面的命令,发布到Dart packages

flutter packages pub publish

在flutter工程中引用插件

引用发布的库

在dependencies加上我们需要引入的库,例如引入url_launcher库:

dependencies:  url_launcher: ^0.4.2

引用未发布的库

基于Path的引用
dependencies:  flutter_plugin:    path: ../
基于Git的引用方式
dependencies:  flutter_plugin:    git:      url: git://github.com/flutter/packages.git      path: packages/package1

在flutter层调用

调用是异步的,关键代码如下:

Future<void> initPlatformState() async {    ...    try {        platformVersion = await FlutterPlugin.platformVersion;    } on PlatformException {        platformVersion = 'Failed to get platform version.';    }    ...}

About

学习flutter

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp