Android原生项目集成Flutter Module

2018-12-13 20:15:58 浏览数 (1)

Flutter安装

git clone下来,然后配置一下path即可

集成步骤

(一)在目标目录的同级目录执行如下命令,创建
代码语言:txt复制
$ flutter create -t module <module_name>
(二)进入到你创建的flutter目录下,执行:
代码语言:txt复制
$ cd .android
$ ./gradlew flutter:assembleDebug

可能出现的错误: 这时候可能卡在resoving dependencies gradle-3.1.4.pom等网络超时错误,这个和AS执行gradle一样需要配置代理。undefined在.android目录下gradle.properties文件配置合适的代理,就可以解决这个问题。 然后可能出现Could not find lint-gradle-api.jar这样的神奇问题,这个的处理方法是:进入到flutter安装的目录下(假定是.flutter),然后修改目录下的.flutter/packages/flutter_tools/gradle/build.gradle文件,将 repositories { jcenter() maven { url 'https://dl.google.com/dl/android/maven2' } } 修改为:repositories { maven { url 'https://dl.google.com/dl/android/maven2' } jcenter() } (其实就是两个位置调换一下,如果某些资源还是找不到,再在前面加一个google()

成功执行后,会在.android/Flutter/build/outputs/aar/目录下,创建一个flutter-debug.aar的包文件

(三)在项目的setting.gradle加上如下代码:
代码语言:txt复制
setBinding(new Binding([gradle: this]))                               
evaluate(new File(                                                 
        settingsDir.parentFile,                                     
        '<module_name>/.android/include_flutter.groovy'               
))

这里是将Flutter项目导入到AS项目中,不过导入的flutter模块只有java代码,想写dart还是要另外开一个IDE。

(四)然后需要在build.gradle(app)中加入如下依赖:
代码语言:txt复制
implementation project(':flutter')

此时sync就一般可以成功了,如果失败了,按照提示逐步解决即可。

笔者这里遇到两个问题,都比较好解决:gradle插件版本问题,flutter模块辛苦3.x以上,需要将主工程的gradle版本升级上去 flutter模块和主工程引用的第三方库版本冲突,常规解决即可,将版本设为一致,或将flutter中的implementation改为api即可

项目中使用Flutter

前面完成了的话,app已经可以run起来了。现在看怎么引入Flutter的代码。

了解了Flutter的知识,其实可以感觉得到,,Flutter中的widget等控件or布局,对于android或iOS来说是透明的,平台只会认为整个Flutter展示的内容是一个view。

所以在android中的用Flutter,就是用一个view去承载Flutter项目。

其实可以理解为flutter就是一个提供了各种绘制方法的view,在Flutter里面的操作就是对view的onDraw方法的控制(还有touch事件)

所以直接当做view去使用的话,就是这样:

代码语言:txt复制
View flutterView = Flutter.createView(
  MainActivity.this,
  getLifecycle(),
  "route1"
);
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(600,800);
layout.leftMargin = 100;
layout.topMargin = 200;
activity.addContentView(flutterView, layout);

对应的Flutter的lib中main.dart文件内容是这样:

代码语言:txt复制
import 'dart:ui';
import 'package:flutter/material.dart';

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

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return SomeWidget(...);
    case 'route2':
      return SomeOtherWidget(...);
    default:
      return Center(
        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
      );
  }
}

window.defaultRouteName会接受到主项目中传入的路由路径,然后返回对应的widget的,之后这个view就完全可以当做一整个Flutter app去对待了。但它的生命周期是由Activity管理的,所以Flutter也可以用Fragment去承载:

代码语言:txt复制
FragmentTransaction tx = fragmentActivity.getSupportFragmentManager().beginTransaction();
tx.replace(R.id.someContainer, Flutter.createFragment("route1"));
tx.commit();

看源码的话,FlutterFragment这里就是将FlutterView wrap了一下,在onCreateView里直接返回了FlutterView。

之后对于FlutterView就是完全是在Flutter项目中开发了。

补充

集成到项目工程中时遇到两个问题。

  • 一个是Flutter不支持armeabi,而我们项目中库都是armeabi的,只能通过将armeab-v7a强行打入armeabi来处理,这样带来的问题是某些不支持armeabi-v7a的cpu设备会无法运行。(目前没有很好的解决方法,不过现在主流的设备都已经支持armeabi-v7a,倒是问题不大。具体数据有待调查)
  • 另一个就是编译时出现错误:没有初始化虚拟机,尝试了各种方法,后来发现前面的编译指令应该去掉flutter:,否则不会打包flutter_assets,这个有点坑~用下面指令就没有问题。
代码语言:txt复制
$ ./gradlew assembleDebug

Wrote by Kevin(a2V2aW56aGFuMDQxN0BvdXRsb29rLmNvbQ==)

0 人点赞