flutter混合開發踩坑之旅

flutter混合開發運行報錯:VM snapshot must be valid. /Check failed: vm. Must be able to initialize the VM.

在安卓原生項目裏集成了flutter_module,按照官方的步驟流程走完再運行原生項目的時候,發現程序啓動之後崩潰,報錯日誌如下:

[ERROR:flutter/runtime/dart_vm_data.cc(19)] VM snapshot invalid and could not be inferred from settings.
[ERROR:flutter/runtime/dart_vm.cc(241)] Could not setup VM data to bootstrap the VM from.
[ERROR:flutter/runtime/dart_vm_lifecycle.cc(89)] Could not create Dart VM instance.
[FATAL:flutter/shell/common/shell.cc(218)] Check failed: vm. Must be able to initialize the VM.

網上找了一下解決方案,大部分都是這種流程:

方案一:

1、 在flutter module的build文件的android節點添加:


project.android.libraryVariants.all { variant ->
    def targetAssets = "${project.buildDir}/intermediates/flutter/${variant.name}"
    def customSourceSet = variant.getSourceSets()[0]
    if (customSourceSet instanceof com.android.build.gradle.internal.api.DefaultAndroidSourceSet) {
        customSourceSet = (DefaultAndroidSourceSet)customSourceSet
        customSourceSet.getAssets().srcDirs(targetAssets)
    }
}

2、 修改flutter_sdk目錄下packages/flutter_tools/gradle/flutter.gradle:

change
variant.outputs[0].processResources.dependsOn(copyFlutterAssetsTask)
to
variant.outputs[0].processResources.dependsOn(flutterTask)

方案二:

github上有一個issues有一個回答,鏈接如下

https://github.com/flutter/flutter/issues/19818

這個哥們比較討巧,他對比了一下apk,發現flutter_assets文件夾沒有打包到assets目錄下, 他說他也不知道爲什麼沒有打包進去。他手工把flutter module編譯出來的flutter_assets的拷貝到安卓項目中,然後重新編譯打包,就沒有問題了,這種方式治標不治本,debug模式下這樣是沒問題了,但是打成release包又奔潰,得編譯release版本的module文件,然後把編譯出來的flutter_assets拷貝到安卓release包中才行

方案三:

1.在AS中打開flutter項目
2.命令行執行:flutter clean
3.cd .android
4…/gradlew clean
5…/gradlew assembleDebug
6.回到Android項目中運行APP(不需要 sync 或 rebuild)

找到$flutterRoot/packages/flutter_tools/gradle/flutter.gradle,搜索copyFlutterAssets。
可以找到有個copyFlutterAssetsTask,就是它沒有被執行,看下gradle裏是怎麼寫的。

根據打印日誌發現走的是上面的if分支,通過代碼可以看出:
gradle根據mainModuleName去找mergeAssets,如果Android項目沒有配置project.rootProject.ext.mainModuleName,就會默認用"app"這個名字去找mergeAssets,r如果app module的名字不是"app",也沒有配置project.rootProject.ext.mainModuleName,就找不到mergeAssets,mergeAssets爲null,就沒有去執行copyFlutterAssets

終極解決方案:在settings.gradle文件中加上mainModuleName的配置

setBinding(new Binding([gradle: this, mainModuleName: '主module名稱']))
evaluate(new File(
        settingsDir.parentFile,
        'my_flutter/.android/include_flutter.groovy'
))

參考:https://blog.csdn.net/l707941510/article/details/98513208
方案三中的flutter.gradle文件在SDK1.7.8版本中還是這個邏輯,但是在最新的SDK(1.9.1)中已經做了修改,邏輯已經改變,是否已經修復該問題我還未驗證,大家可以試一下

我採用了第三種方案,,產生這個的原因主要是由於不同模式下的產物沒有清理使用了緩存,刪除掉所有build文件的內容再全量編譯一次,先在flutter module所在的項目跑一遍(包含.android的項目),然後運行宿主所在的項目,,,發現問題就解決了。。

flutter finished with non-zero exit value 1

這個問題的出現方式是,項目引用着某個flutter_module,然後換成另一個flutter_modlue,同步一下文件,發現報這個錯,解決方式很簡單,把主項目的build文件刪除,然後clean build就行了

a globalkey was used multiple times inside one widget’s child list

這個問題出現的情況是第一次集成某個flutter_module,然後從原生入口點擊進入flutter頁面,然後模擬器界面出現了這個提示,找了好久並沒有發現合適的方案,遇見這個問題的人也不多,,最後我跑了一下flutter_module,再回來跑主項目,就可以了。。好坑。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章