flutter Android部分机型安装release包打开后随机黑屏

前期开发调试时一直都是在真机上运行的debug包,没有发现随机黑屏的问题,准备上架打release包后发现部分Android的机型会出现随机黑屏的问题,查了资料后说有以下原因:

1.混淆(未解决):

在android/app/build.gradle文件中添加以下配置

buildTypes {
    release {
        minifyEnabled false //关闭混淆
        shrinkResources false //删除无用资源
        signingConfig signingConfigs.release
        ...
    }
}

2.关闭R8压缩,使用D8压缩(未解决):

在android/gradle.properties文件中增加

# 开启D8压缩
android.enableD8=true
# 关闭R8压缩
#android.enableR8=true

以上尝试后都没有解决问题,又考虑是否是Android和flutter生命周期不一致?项目使用了fishredux框架?

在android/app/src/main/kotlin/.../MainActivity.kt文件中写入Android原生的生命周期,重新编译后发现没执行这个文件,因为没有接触过Android原生,因此造成未执行的具体原因不清楚,但想来和生命周期不一致没关系。

将页面替换为flutter原生的写法不使用fishredux,重新编译后也没有解决问题。

到这里这个问题已经卡了我一周多了,没有报错无法定位问题,release也无法打断点,有点绝望,最后想实在不行就重构?那会不会是依赖或者环境的配置有问题?这样的话只能一个依赖一个依赖排查,重新搭环境看是哪里的问题,但着急上线哪有那么多时间真的想哭...。

我先排查了是否是依赖的问题,flutter create了一个新的项目,依次把原项目的依赖引入,发现依赖没问题,但这个新项目打release是没有黑屏问题的!那和原项目的区别就只在于入口的main文件不一样,把新建项目的main文件替换到原项目,打release后没有出现黑屏,OK!就是main文件里的问题!!!

以下为问题原因!解决!!!

main文件中有这样一段代码:

window.physicalSize监听屏幕尺寸大小,当不为空时执行window.onMetricsChanged回调

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

怀疑是这段代码的问题,于是把这段中的逻辑判断都注掉,只留了runApp,重新编译后发现没有黑屏了但随机出现页面错乱的现象。

出现黑屏和页面错乱的原因是flutter为了加快启动速度,屏幕尺寸还为空时就渲染页面。查了一下runApp前必须先WidgetsFlutterBinding.ensureInitialized(),确保有WidgetsFlutterBinding实例,修改上述代码为:

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

void runMyApp() async{
    WidgetsFlutterBinding.ensureInitialized();
    runApp(MyApp());
}

编译后依旧没有解决问题,在Stack Overflow上有人遇到了同样的问题,提供了一段代码:

import 'dart:async';
import 'dart:ui';
import 'package:flutter/widgets.dart';

Future<void> waitScreenSizeAvailable() async {
  if (!_hasScreenSize) {
    WidgetsFlutterBinding.ensureInitialized();
    var observer = _Observer();
    WidgetsBinding.instance.addObserver(observer);
    await observer.hasScreenSize;
    WidgetsBinding.instance.removeObserver(observer);
  }
}

bool get _hasScreenSize => !window.physicalSize.isEmpty;

class _Observer extends WidgetsBindingObserver {
  final _screenSizeCompleter = Completer<void>();

  Future<void> get hasScreenSize => _screenSizeCompleter.future;

  @override
  void didChangeMetrics() {
    if (!_screenSizeCompleter.isCompleted && _hasScreenSize) {
      _screenSizeCompleter.complete();
    }
  }
}

修改main文件中的代码为:

if(window.physicalSize.isEmpty){
    window.onMetricsChanged = () async {
        //在回调中,size仍然有可能是0
        if(!window.physicalSize.isEmpty){
            window.onMetricsChanged = null;
            await waitScreenSizeAvailable(); //引入上面那段代码
            runMyAPP();
        }
    };
} else{
    //如果size非0,则直接runApp
    await waitScreenSizeAvailable(); //引入上面那段代码
    runMyAPP();
}

编译后问题解决!!!!!

这个问题前后卡了快两周,全程没有任何报错信息导致无法定位问题,再加上release没法打断点,只能盲猜问题可能在哪再一步步排查。不过总算是解决了,泪目...

猜你喜欢

转载自blog.csdn.net/YML_426/article/details/129730925