天天看點

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

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

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

這個哥們比較讨巧,他對比了一下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裡是怎麼寫的。

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

根據列印日志發現走的是上面的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,再回來跑主項目,就可以了。。好坑。。。