前言
Flutter是Google开源的构建用户界面(UI)工具包
 支持在不同平台构建一致的ui效果
 但在实际业务中,一般不会整个APP都用纯Flutter开发
 尤其一些老的项目,会采用接入Flutter的方式来混合开发
 那么今天就主要讲一下如何搭建一个Flutter的混合项目
混合项目实现方式
目前官方提供了两种方式添加依赖关系,他们的介绍分别如下:
方式一:模块代码依赖模式
这种方式是将flutter代码引入android项目,flutter代码对原生可见
 好处是确保了一步完成Android项目和Flutter模块的编译。
 对于同时涉及两个部分并且快速迭代很方便,
 但这需要团队的每个人成员都安装Flutter SDK来确保顺利编译这个混合app。
方式二:AAR依赖模式
这种方式是将flutter代码打包成aar引入android项目,flutter代码对原生不可见
 AAR模式有个好处就是团队中的其他成员不需要安装Flutter SDK,
 最少只需要一个人输出AAR即可。
限于篇幅原因,今天这篇博客主要讲方式一的实现,
 方式二的我单独写了一篇博客:
 Flutter基础入门:手把手教你搭建Flutter混合项目:AAR方式集成
模块代码依赖模式实现
手动创建Flutter模块
首先我们新建一个简单的Android项目
 然后进入到项目目录
 打开cmd窗口,输入以下命令:
flutter create -t module --org com.xiongyp flutterxiongmodule
 
这样就创建了一个包名为com.xiongyp.flutterxiongmodule的Flutter模块
 这里注意一点,Flutter模块放在其他目录下创建也是可以的
 只要后面配置好地址,能链接到这个目录就好
引入Flutter模块
在Android项目的settings.gradle中将Flutter模块作为子项目引入
 settings.gradle这样写:
rootProject.name = "FlutterHybridProject"
include ':app'
setBinding(new Binding([gradle: this]))                                           // 新增
evaluate(new File(                                                                // 新增
        settingsDir.parentFile,                                                   // 新增
        "${rootProject.name}/flutterxiongmodule/.android/include_flutter.groovy"  // 新增
))                                                                                // 新增
include ':flutterxiongmodule'
 
这里注意下:如果你的Flutter模块放在其他目录下
 记得把include_flutter.groovy文件的路径配置准确
 也就是这一行:
"${rootProject.name}/flutterxiongmodule/.android/include_flutter.groovy"
 
配置好了之后将settings.gradle的
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
    }
}
 
改为:
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
    }
}
 
区别主要在:RepositoriesMode.PREFER_PROJECT
 具体解释为:
FAIL_ON_PROJECT_REPOS :在项目的子 module 中配置仓库信息会导致编译失败。
PREFER_PROJECT:使用子 module 中配置仓库信息,忽略根目录中 settings 配置的仓库信息
PREFER_SETTINGS:使用根目录中 settings 配置的仓库信息,忽略子 module 中配置仓库信息
 
完成上面操作后,在project的build.gradle的
task clean(type: Delete) {
    delete rootProject.buildDir
}
 
上方添加:
allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}
 
完整的build.gradle的文件如下:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = '1.7.10'
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}
 
至此,大体上一个混合的Android原生+Flutter项目的初步构建就完成了。
 接下来就是页面的跳转了
页面跳转
Android原生打开Flutter页面
 默认的跳转方式会出现明显的白屏,体验上很不好,这里直接给出优化后的方式
 使用FlutterEngine缓存并复用
 1.在app的AndroidManifest.xml中注册FlutterActivity
    <activity
      android:name="io.flutter.embedding.android.FlutterActivity"
      android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
      android:hardwareAccelerated="true"
      android:windowSoftInputMode="adjustResize" >
    </activity>
 
2.在app中创建一个App.kt继承Application并在AndroidManifest.xml中配置给application节点的name属性
class App : Application() {
    ···
}
 
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xiongyp.flutterxiongmodule">
    <application
        android:name=".App"
        ···
</manifest>
 
3.在App.kt中准备好FlutterEngine
 创建FlutterEngine实例
    private val flutterEngine by lazy {
        FlutterEngine(this).apply {
            dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
        }
    }
 
重写onCreate()并将实例存储在FlutterEngineCache中
override fun onCreate() {
    super.onCreate()
    FlutterEngineCache.getInstance().put("your_engine_id", flutterEngine)
}
 
重写onTerminate()并将实例销毁
override fun onTerminate() {
    super.onTerminate()
    flutterEngine.destroy()
}
 
在业务需要的地方使用FlutterEngine中的Intent实例进行跳转
    findViewById<TextView>(R.id.textView).setOnClickListener {
        startActivity(FlutterActivity.withCachedEngine("your_engine_id").build(this))
    }
 
选择app进行run,如果遇到如下Java版本问题,请进行如下配置变更
A problem occurred evaluating project ':flutter'.
> Failed to apply plugin 'com.android.internal.library'.
   > Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
     You can try some of the following options:
       - changing the IDE settings.
       - changing the JAVA_HOME environment variable.
       - changing `org.gradle.java.home` in `gradle.properties`.
 
选择 Project Structure > SDK location > Gradle Settings 设置Gradle JDK为11
 
 在./gradle.properties中添加上文中对应的java.home路径
# replace with your own jdk11 or above
org.gradle.java.home=C\:\\Softwares\\Google\\Android\\Android_Studio\\jre
 
sync后应该就可以顺利的运行你的项目了
导入Moudle
上面讲的是用flutter命令创建了FlutterMoudle然后引入到安卓工程
 其实也可以用Android Studio来创建一个FlutterMoudle
 下面讲两种用Android Studio来创建一个FlutterMoudle的方法
方式一
如下图:
 
 之后输入Flutter module的Project name,选择Flutter SDK所在的路径,选择Flutter module的文件位置,最后输入Flutter module的描述,然后Next,如下图所示
 
 上诉基本信息填充完毕后,点击Next,在弹出的面板中输入Flutter module的包名,如下图所示
 
 输入Package name后点击Finish后Flutter module就正式创建完毕。
 创建好的flutter module和新建的flutter项目在内容上基本没有差别。
方式二
当然,有的人会发现自己的Android Studio在创建Moudle时没有Flutter Moudle选项,如下图
 
 估计是不同版本AS的区别,这时我们可以选择创建Flutter Project
 
 选择下一步:
 
 然后在下拉框里选择moudle,点击create就好了
 
 注意,创建好的FlutterMoudle记得在Android项目的settings.gradle里配置好路径
 你也可以直接放到Android项目的目录下,然后配置路径
gradle版本适配
上面讲的是Gradle7.X的项目如何集成FlutterMoudle进行混合开发
 具体Gradle7.X有哪些改变,可以上网查下资料或参考下面博文:
 gradle7 从上手到实践之上手体验
 那么如果是老的项目,它的Gradle版本和写法是7.X之前的,就需要另外处理
 这里也提一下
 首先是settings.gradle文件,写法和之前差不多,全部内容如下:
rootProject.name = "FlutterHybridProject"
include ':app'
setBinding(new Binding([gradle: this]))                                // 新增
evaluate(new File(                                                     // 新增
        settingsDir.parentFile,                                              // 新增
        "${rootProject.name}/flutterxiongmodule/.android/include_flutter.groovy"  // 新增
))                                                                     // 新增
include ':flutterxiongmodule'
 
改动比较大的是build.gradle文件,这里也全部贴上来:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = '1.7.10'
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}
 
至此,第一种搭建Flutter混合项目的方式就讲完了
源码分享以及使用
文章里相关代码都放到gitee上面了,需要的可以自取哈
 FlutterHybridProject
 不同的分支是各自的集成方式示例,区别如下:
- master 一个简单的安卓Helloworld项目
 - old_gradlesetting 模块代码依赖模式:Gradle版本低于Gradle7.X方式集成
 - new_gradlesetting 模块代码依赖模式:Gradle7.X方式集成
 - aar_flutter AAR依赖模式:基于Gradle7.X版本
 
在你引用其他人的FlutterMoudle或者网上下载一些FlutterMoudle案例时
 如果发现FlutterMoudle里面没有.android .ios .idea 等临时文件不存在时
 可以在FlutterMoudle文件夹下打开cmd控制台
 输入以下命令:
flutter create .
 
回车后系统便会自动为你生成这些对应的临时文件了
 这时你就可以正常运行项目并进行开发了!
 参考解决方法:
 Flutter 报错 ( Could not read script ‘xxx\flutter_tools\gradle\app_plugin_loader.gradle‘ )



















