在上一篇文章《Flutter工程结构详解(Android视角)》,咱们说了flutter工程的整体结构和flutter工程中几个重要文件的效果,下面咱们就来要点说一下,flutter工程怎么与android混编在一起的。

这里,咱们就要要点分析一下android这个目录下的一些重要文件了,咱们先来看一下android文件夹都有那些东西。

Flutter工程详解(二):Flutter工程如何与Android混编

咱们来看,里边与咱们平常创立的传统android工程看起来不同并不太大,app是咱们终究的生成apk文件的module,在app这个module里,你仍然能够写你现已把握的android原生代码(Java或者Kotlin)去完结你想要经过原生完结的功用,这个相信咱们能够了解,那再往下这个Flutter文件夹是个什么呢,其实他是一个library,这个library有什么效果呢,咱们先看一下他的build.gradle文件有些什么就清楚了。

// 我删掉了一些不影响了解的检查类型的代码
apply plugin: 'com.android.library'  //阐明Flutter工程是个android Library
//引进了flutter sdk中的一个flutter.gradle文件,非常重要,第一个不同点
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
// 指定flutter工程的目录,第二个不同点。
flutter {
    source '../..'
}

咱们来看,是不是也没有什么东西,与咱们平常创立的android library也没有什么不同,不同之处,只要两点,一点是引进了一个flutter.gradle文件,一点是装备了一个flutter{}的extension,可是,便是这两点,帮咱们完结了flutter工程打入到此library中的一切功用,尤其是第一点,引放flutter sdk中的flutter.gradle文件,所以咱们下面就来要点看一下这个flutter.gradle文件中的核心内容,看看他是怎么帮咱们将flutter工程的内容打包到咱们的这个Flutter库工程中的,代码如下:

// 核心便是一个自定义plugin,并主动帮咱们引进
apply plugin: FlutterPlugin
class FlutterPlugin implements Plugin<Project> {
     // 此plugin的核心办法。只挑选要点部分
     @Override
    void apply(Project project) {
      //第一点,主动帮咱们依靠flutter.jar 
      flutterJar = Paths.get(engineOut.absolutePath, "flutter.jar").toFile()
            if (!flutterJar.isFile()) {
                throw new GradleException('Local engine build does not contain flutter.jar')
            }
            localEngine = engineOut.name
            localEngineSrcPath = engineOut.parentFile.parent
            project.dependencies {
                if (project.getConfigurations().findByName("api")) {
                    api project.files(flutterJar)  //plugin3.0以上的api方法依靠
                } else {
                    compile project.files(flutterJar) //plugin3.0以下的compile依靠
                }
            }
      // 第二点,创立上文提到的flutter这个extension和FluterTask这个Task,一瞬间咱们来详细看task的效果
      project.extensions.create("flutter", FlutterExtension)
      project.afterEvaluate this.&addFlutterTask
      //第三点,读取.flutter-plugins文件中的一切依靠plugin,并添加到Flutter工程中的build.gradle依靠中
      File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins')
        Properties plugins = readPropertiesIfExist(pluginsFile)
        plugins.each { name, _ ->
            def pluginProject = project.rootProject.findProject(":$name")
            if (pluginProject != null) {
                project.dependencies {
                    if (project.getConfigurations().findByName("implementation")) {
                        implementation pluginProject
                    } else {
                        compile pluginProject
                    }
                }
		pluginProject.afterEvaluate {
                    pluginProject.android.buildTypes {
                        profile {
                            initWith debug
                        }
                    }
		}
                pluginProject.afterEvaluate this.&addFlutterJarCompileOnlyDependency
            } else {
                project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
            }
        }
    }
  //第二点中提到的创立FlutterTask办法
  private void addFlutterTask(Project project) {
        //找到flutter工程中的lib下的进口main.dart
        String target = project.flutter.target
        if (target == null) {
            target = 'lib/main.dart'
        }
        // 处理flutter中的dart代码
        def addFlutterDeps = { variant ->
            FlutterTask flutterTask = project.tasks.create(name: "${flutterBuildPrefix}${variant.name.capitalize()}", type: FlutterTask) {
                flutterRoot this.flutterRoot
                flutterExecutable this.flutterExecutable
                buildMode flutterBuildMode
                localEngine this.localEngine
                localEngineSrcPath this.localEngineSrcPath
                targetPath target
                verbose verboseValue
                fileSystemRoots fileSystemRootsValue
                fileSystemScheme fileSystemSchemeValue
                trackWidgetCreation trackWidgetCreationValue
                compilationTraceFilePath compilationTraceFilePathValue
                buildHotUpdate buildHotUpdateValue
                buildSharedLibrary buildSharedLibraryValue
                targetPlatform targetPlatformValue
                sourceDir project.file(project.flutter.source)
                intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}")
                extraFrontEndOptions extraFrontEndOptionsValue
                extraGenSnapshotOptions extraGenSnapshotOptionsValue
            }
           //处理flutter工程中的asset
            Task packageAssets = project.tasks.findByPath(":flutter:package${variant.name.capitalize()}Assets")
            Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets")
            Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) {
                dependsOn flutterTask
                dependsOn packageAssets ? packageAssets : variant.mergeAssets
                dependsOn cleanPackageAssets ? cleanPackageAssets : "clean${variant.mergeAssets.name.capitalize()}"
                into packageAssets ? packageAssets.outputDir : variant.mergeAssets.outputDir
                with flutterTask.assets
            }
            if (packageAssets) {
                // Only include configurations that exist in parent project.
                Task mergeAssets = project.tasks.findByPath(":app:merge${variant.name.capitalize()}Assets")
                if (mergeAssets) {
                    mergeAssets.dependsOn(copyFlutterAssetsTask)
                }
            } else {
                variant.outputs[0].processResources.dependsOn(copyFlutterAssetsTask)
            }
        }
    }
}

经过上面临Flutter这个library以及flutter sdk中的flutter.gradle文件的代码进行学习,咱们能够发现,这个Flutter module自身没有任何的详细逻辑,他的仅有效果便是经过引进flutter sdk中的flutter.gradle,主动完结将flutter工程中的lib下的代码和asset下的资源打包到其间,这样这个Flutter安卓module终究能够生成一个带有flutter代码和资源的aar包,最终这个aar包就能够被其它的app去运用.

那在我这个demo工程,app是怎么运用到包括flutter代码的这个aar包的呢,下面咱们打开app下的build.gradle文件来看一下,

// 修改apk的输出方位为根目录下的build/host
buildDir = new File(rootProject.projectDir, "../build/host")
dependencies {
   //这里便是apk直接依靠了咱们的Flutter这个library的源码,也能够经过maven的方法引用咱们Flutter module生成的aar,道理相信咱们都理解.
   implementation project(':flutter')
   implementation fileTree(dir: 'libs', include: ['*.jar'])
   implementation'com.squareup.okhttp3:okhttp:3.3.0'

这里有一个问题,咱们的library module叫Flutter,但咱们的app的build.gradle中运用的却是flutter,这个呢相对来说简略的许多,要看咱们最终一个文件,include_flutter.groovy这个文件,要点代码如下:

//include咱们创立的Flutter工程并命名为flutter
def scriptFile = getClass().protectionDomain.codeSource.location.path
def flutterProjectRoot = new File(scriptFile).parentFile.parentFile
gradle.include ':flutter'
gradle.project(':flutter').projectDir = new File(flutterProjectRoot, '.android/Flutter')
//引进一切的plugin工程,下一末节详细讲plugin工程
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 ":$name"
    gradle.project(":$name").projectDir = pluginDirectory
}

好,到此咱们就应该知道,咱们的android工程是怎么引进了flutter工程中的东西,然后将他们打包到同一个apk中去的,从工程层面上了解了他们怎么合二为一今后,详细在代码层面怎么调用,便是经过plugin最终完结flutter和android原生的通信。最终咱们以一张图来总结一下今日所讲的内容:

Flutter工程详解(二):Flutter工程如何与Android混编
收录自|原文地址

欢迎重视:

Flutter Mac/Flutter Windows下载安装,环境搭建

Flutter开发实战:高仿微信(一)首页

Flutter开发实战:高仿微信(二)发现页