flutter 编译报错总结(不断更新)

1、Cannot fit requested classes in a single dex file#

问题

Cannot fit requested classes in a single dex file (# methods: 66370 > 65536)

原因分析

主要原因是你的项目貌似有点大,已经超过 65k 个方法。一个 dex 已经装不下了,需要个多个 dex,也就是 multidex ,因为 Android 系统定义总方法数是一个 short int,short int 最大值为 65536。

解决方案

  1. 在 app module 中的 build.gradle 中添加依赖
    implementation 'com.android.support:multidex:1.0.3' 
    //
    dependencies {
        implementation fileTree(include: ['*.jar'], dir: 'libs')
        implementation 'com.android.support:appcompat-v7:28.0.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
        //添加到此处
        implementation 'com.android.support:multidex:1.0.3'
    }
  2. 在 app module 中的 build.gradle 中的 defaultConfig 中添加以下代码
    android {
        compileSdkVersion 28
        defaultConfig {
            applicationId "com.example.demo"
            minSdkVersion 16
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            //添加到此处
            multiDexEnabled true
        }
    }

2、Flutter 在 profile 和 release 模式下的白屏问题#

import 'dart:ui';//window需要import ui库

void main(){
  //如果size是0,则设置回调,在回调中runApp
  if(window.physicalSize.isEmpty){
    window.onMetricsChanged = (){
      //在回调中,size仍然有可能是0
      if(!window.physicalSize.isEmpty){
        window.onMetricsChanged = null;
        runApp(MyApp());
      }
    };
  } else{
    //如果size非0,则直接runApp
    runApp(MyApp());
  }
}

分析#

这段代码里有两个东西需要了解一下的,第一个是 window.onMetricsChanged,源码的注释是这样写的

/// A callback that is invoked whenever the [devicePixelRatio],\
/// [physicalSize], [padding], or [viewInsets] values change, for example\
/// when the device is rotated or when the application is resized (e.g. when\
/// showing applications side-by-side on Android).

也就是当 devicePixelRatio、physicalSize、padding、viewInsets 这几个东西变化时会触发的回调,其中屏幕大小就是 physicalSize

第二个是 physicalSize,上面说了这个是屏幕大小,但是它一开始是 0*0,直到 Flutter 初始化时将它赋值为屏幕大小才能获取到非 0 的值

好了,说完了上面两个东西,就来说说问题。问题的坑点在于,mian() 方法并不是在 Flutter 给 physicalSize 赋值后才运行的,两者并没有固定的先后顺序,从测试来看,跟设备的性能有关

之前的错误解法#

之前是下面这样写的,然后在新 ipad air 的 profile 模式下以及所有机型的 debug 模式下都会白屏,只有比较旧的 mini4 不会白屏

void main(){
  window.onMetricsChanged = (){
    runApp(MyApp());
    window.onMetricsChanged = null;
  };
}

经排查,发现原因是 mini 够慢,在设置了 onMetricsChanged 回调后 flutter 还没有读取到屏幕 size,也就还没出触发 onMetricsChanged。

然而在新 air 上,则是几率性的,有时和 mini 一样,有时在设置 onMetricsChanged 之前 flutter 就已经读取了屏幕 size 了,所以后面一段时间都不会触发 onMetricsChanged,导致白屏。更奇怪的是,有时设置的 onMetricsChanged 倍触发后,仍然是白屏,排查后发现 air 上不止一次 resize,而只有最后一次非 0。

所以完整的代码中有这一段保护:

window.onMetricsChanged = (){
  //这里仍然有可能是0
  if(!window.physicalSize.isEmpty){
    window.onMetricsChanged = null;
    runApp(MyApp());
  }
};

链接:https://www.jianshu.com/p/4f0651241956\

本作品采用《CC 协议》,转载必须注明作者和本文链接