Flutter是Google用以帮助开发者在Ios和Android两个平台开发高质量原生应用的全新移动UI框架
优势:
- 热重载。利用Android Studio直接一个ctrl+s就可以保存并重载,模拟器立马就可以看见效果。
- 一切皆为 Widget 的理念。对于Flutter来说,手机应用里的所有东西都是Widget,通过可组合的空间集合、丰富的动画库以及分层课扩展的架构实现了富有感染力的灵活界面设计。
- 借助可移植的GPU加速的渲染引擎以及高性能本地代码运行时以达到跨平台设备的高质量用户体验。利用Flutter构建的应用在运行效率上会和原生应用差不多。
具体介绍可参考:你好,Flutter
1.2 - 新建 Flutter 工程
如不做特殊说明,文中所操作的工程都是
Module
工程。
在开始接入之前,先在Android Studio下载Flutter、Dart两个插件,插件安装完成之后,新建一个Flutter工程。
Flutter工程有四种类型选择,开发主要选择 Flutter Application 和 Flutter Module。
Application 与 Module 工程差别
- 前者作为一个独立的app运行,后者的
Flutter
子模块可以作为其他工程的依赖。 - 前者用文件夹
android
来保存android代码,后者使用.android
来保存,且后者的.android
文件夹是隐藏的。 - 进入
android
文件夹内部,前者只有app
一个工程,在新建的时候可以选择是否支持kotlin
或者swift
,后者有两个工程app
和Flutter
,Flutter
作为子模块被app
所依赖。
1.3 - 一些重要的 gradle 文件
- app 模块下的 build.gradle
android {
…
}
// 在编译过程中产生的中间产物将会存放在该文件夹下
buildDir = new File(rootProject.projectDir, “…/build/host”)
dependencies {
implementation project(‘:flutter’)
…
}
主工程 app
依赖了子模块 :flutter
,但是我们在工程中并没有使用以flutter
命名的子模块。
- Flutter 模块下的 build.gradle
def localProperties = new Properties()
def localPropertiesFile = new File(buildscript.sourceFile.parentFile.parentFile, ‘local.properties’)
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader(‘UTF-8’) { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty(‘flutter.sdk’)
if (flutterRoot == null) {
throw new GradleException(“Flutter SDK not found. Define location with flutter.sdk in the local.properties file.”)
}
def flutterVersionCode = localProperties.getProperty(‘flutter.versionCode’)
if (flutterVersionCode == null) {
flutterVersionCode = ‘1’
}
def flutterVersionName = localProperties.getProperty(‘flutter.versionName’)
if (flutterVersionName == null) {
flutterVersionName = ‘1.0’
}
在初次点开该 gradle 文件时会在
GradleException
处标红,不用解决,不影响正常编译。
这边主要是从local.properties
获取一些配置数据,如 flutter sdk 位置等等。
apply plugin: ‘com.android.library’
apply from: “$flutterRoot/packages/flutter_tools/gradle/flutter.gradle”
android {
compileSdkVersion 28
defaultConfig {
…
}
}
flutter {
source ‘…/…’
}
dependencies {
…
}
在第二行通过apply from 引入了 flutter.gradle
文件,其主要作用是为 Flutter
模块引入 flutter 相关依赖,.so文件等等。
注意:flutter 模块要求 compileSdkVersion >= 28,对于很多使用 kotlin 代码且工程 sdk 低于 28 的可能有毁灭性的打击,会报 onCreate() override nothing等类型不匹配的错误,需要一一手动修改错误。
flutter
结构体主要表示flutter源码的位置,../..
的意思就是Flutter
文件夹下的代码就是源码。
- .android/setting.gradle
include ‘:app’
rootProject.name = ‘android_generated’
setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir, ‘include_flutter.groovy’))
打开文件后,Binding类也会报错,此时不要为其 import ,不然会报错,报红不影响编译。
这几行代码的意思就是说,将 Flutter 模块引入到Android工程中。Flutter 模块并没有显示地使用 include ':flutter'
,那为什么 Flutter 模块会以 :flutter
这样的形式被依赖呢?带着问题,我们看看include_flutter.groovy
。
- .android/include_flutter.groovy
gradle.include ‘:flutter’
gradle.project(‘:flutter’).projectDir
= new File(flutterProjectRoot, ‘.android/Flutter’)
可以看到,文件内仍然是通过 include ':flutter'
语法引入到 Android 工程内,同时为其指定模块位置为 Flutter 文件夹
。
if (System.getProperty(‘build-plugins-as-aars’) != ‘true’) {
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot, ‘.flutter-plugins’)
if (pluginsFile.exists()) {
pluginsFile.withReader(‘UTF-8’) { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve(‘android’).toFile()
gradle.include “:
n
a
m
e
"
g
r
a
d
l
e
.
p
r
o
j
e
c
t
(
"
:
name" gradle.project(":
name"gradle.project(":name”).projectDir = pluginDirectory
}
}
这边是调用 flutter build aar
指令(仅在 flutter module 工程下可用)编译输出 aar 文件时会被调用的,其目的就是将 flutter 工程用到的第三方组件打到输出到 aar 中方便 Native 工程引入。
- flutterRoot/packages/flutter_tools/gradle/flutter.gradle
flutterRoot 是 flutter sdk 所在的位置。具体内容可以查看 揭开Flutter工程编译的面纱(Android篇)。
二、接入
目前 Native 工程接入 Flutter 工程有两种方式:
- 将上文提到的
Flutter
模块作为依赖引入到 Native- 以 aar 形式引入到 Native 工程
2.1 - 以 module 方式集成
该方式集成是最简单轻松的。native 工程名称为 FlutterNativeProject
,flutter 工程名称为 flutter_module_project
2.1.1 - 步骤1
将 flutter module 工程整个拷入到 native 工程中。(本文只是从 git 管理的角度放在 native 工程下,当然也可以在其他位置,只需在配置文件配置)
2.1.2 - 步骤2 :修改 setting.gradle
include ‘:app’
rootProject.name=‘FlutterNativeProject’
rootProject.name = ‘android_generated’
setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir,
‘/flutter_module_project/.android/include_flutter.groovy’))
注意修改 include_flutter.groovy
位置为实际工程中的地址,这边引入 ':flutter'
,但 native 工程还没有依赖它。
2.1.3 步骤3:修改 native 工程下 app 的 build.gradle
dependencies {
implementation project(‘:flutter’)
}
试一把:在 MainActivity 里面加入 Flutter 代码:
报红??????看一下报的错误吧。
Type mismatch.
Required: Lifecycle!
Found: androidx.lifecycle.Lifecycle
看来是类型不匹配啊,androidx 是 support 包整合之后,用以解决 support 包混乱的问题,没关系,换成 support(flutter 也支持 androidx,在新建工程的时候下方有个选项是否使用 androidX,28 版本是 support 库最后支持的版本,后面都要使用 androidX)。同时,将 gradle.properties
设置为useAndroidX=false
、enableJetifier=false
// 将 androidx 依赖改成这个
implementation “com.android.support:appcompat-v7:28.0.0”
再试一把:加入代码
setContentView(flutterView)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
FlutterMain.startInitialization(this)
val flutterView = Flutter.createView(this, lifecycle, “/main”)
setContentView(flutterView)
}
}
可以简单理解为创建了一个 View,然后设置为布局
@NonNull
public static FlutterView createView(@NonNull final Activity activity,
@NonNull final Lifecycle lifecycle,
final String initialRoute)
initialRoute
:在 flutter 中设置的页面路由,而在 flutter 工程默认生成的工程中,flutter_module_project/lib/main.dart
没有配置路由,给其配置一个路由:
再试亿把:编译成功了,下载到手机中试一试 方式1:as 里面的 run 方式2:打开 terminal ,输入
flutter run
作为未来的外卖员,该选哪个你心里没点数吗?肯定第一种啊!
Default interface methods are only supported starting with Android N (–min-api 24): void android.arch.lifecycle.DefaultLifecycleObserver.onCreate(android.arch.lifecycle.LifecycleOwner)
在 native 工程的 build.gradle 里面添加如下代码:
android {
…
defaultConfig{
…
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
}
到这里就成了!我们是冠军!
看一下成果(忽略这丑陋的一切):
2.2 - 以 aar 形式引入
在开始骚操作之前,先解剖一下刚刚成功生成的 apk 文件:
libflutter.so
和flutter_assets
是 flutter 运行必备的资源,前者是flutter 框架基础,后者就是 lib 文件夹下的 dart 代码,这就是坑的开始。
2.2.1 - 步骤1:生成 aar
–> 进入 flutter module 工程
两种方式:
- 进入 .android 文件夹,打开 Terminal,输入指令:
./gradlew assembleDebug
编译结束后,在.android/Flutter/build/outputs/aar
下找到flutter-debug.aar
- 在 flutter 工程下(注意位置,一定要在 pubspec.yaml 同级目录下)打开 Terminal,输入指令:
flutter build aar --debug // 后面会解释 debug 与 release 的区别
–> 注意:我们在拉 flutter sdk 的时候,一般是在 github 上 clone,目前该指令只在 master 分支上有效。位置在flutter_module_project/build/host/outputs/repo/com/example/flutter_module_project/flutter_debug/1.0/flutter_debug-1.0.aar
两种方式生成的 aar 文件相同。
2.2.2 - 步骤2:在 native 工程中引用
为了引入 aar,需要在 native 外层的 build.gradle 中添加如下代码,不然会出现找不到 aar 文件的问题:
allprojects {
本文在开源项目:Android开发不会这些?如何面试拿高薪! 中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
负担。**
[外链图片转存中…(img-SBKs8bc5-1710957173012)]
[外链图片转存中…(img-Rlk8YEUJ-1710957173012)]
[外链图片转存中…(img-dwBu4Tck-1710957173013)]
[外链图片转存中…(img-HGw0GuzI-1710957173013)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-c3oAWK8G-1710957173014)]