Flutter发布模式白屏求助:关联SharedPreferences与Kotlin通知代码
Flutter Release模式启动白屏/停在闪屏,Debug模式正常(添加Kotlin本地通知代码后触发)
问题描述
Debug模式下应用运行完全正常,但切换到Release模式后,启动时要么显示白屏,要么卡在闪屏页面,无法进行导航和交互。这个问题是在添加了用于发送、设置本地通知的Kotlin代码后出现的,而且Debug模式没有明显报错,定位问题很困难。
应用必须依赖初始化的Services才能正常运行,如果取消初始化Services,应用虽然能启动,但界面处于实验性状态,无法正常使用。
相关代码
主入口代码(main.dart)
import 'package:al_muezzin/bindings/initialbindings.dart'; import 'package:al_muezzin/core/constant/color.dart'; import 'package:al_muezzin/core/localization/translation.dart'; import 'package:al_muezzin/core/service/services.dart'; import 'package:al_muezzin/route.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:timeago/timeago.dart' as timeago; void main() async { WidgetsFlutterBinding.ensureInitialized(); await initialServices(); timeago.setLocaleMessages('ar', timeago.ArMessages()); runApp(const MyApp()); } final MethodChannel _channel = MethodChannel('com.example.al_muezzin/AlarmManagement'); Future<void> setNextAlarm() async { try { await _channel.invokeMethod('setNextAlarm'); } on PlatformException catch (e) { Fluttertoast.showToast(msg: 'Failed to set alarm: ${e.message}'); } } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return GetMaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', theme: ThemeData( fontFamily: 'AL-JAZEERA', appBarTheme: AppBarTheme( backgroundColor: AppColor.secondColor ), scaffoldBackgroundColor: Color(0xffF2F2F2), ), locale: Locale('ar'), translations: MyTranslation(), initialBinding: InitialBindings(), getPages: getPages, ); } }
服务初始化代码(services.dart)
import 'package:al_muezzin/core/function/print.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; class MyServices extends GetxService { late SharedPreferences sharedPreferences; Future<MyServices> init() async { sharedPreferences = await SharedPreferences.getInstance(); return this; } } initialServices() async { await Get.putAsync(() => MyServices().init()); }
排查与解决方案
1. 优先排查Kotlin原生代码的Release兼容性
问题是添加Kotlin通知代码后出现的,先从原生层入手:
- 检查Kotlin代码中是否有仅Debug模式生效的逻辑(比如依赖调试日志、测试权限),Release模式下这些逻辑失效会导致阻塞。
- 确认MethodChannel注册是否正确:确保在Android的
MainActivity或自定义Application类中,正确注册了com.example.al_muezzin/AlarmManagement通道,Release模式下通道未注册会导致方法调用阻塞,卡住初始化流程。 - 检查通知权限申请逻辑:Release模式下权限策略更严格,若权限申请失败且未做异常处理,会导致后续代码阻塞。可以在初始化Services前主动申请
POST_NOTIFICATIONS权限,确保权限获取成功后再执行后续操作。
2. 排查Release模式下的初始化阻塞
应用依赖initialServices()完成初始化,Release模式下该方法可能因异常卡住:
- 给初始化方法添加错误捕获与日志输出:
用initialServices() async { try { await Get.putAsync(() => MyServices().init()); print('Services initialized successfully'); } catch (e) { print('Services init failed: $e'); } }flutter run --release启动应用,通过adb logcat查看原生日志,定位初始化过程中的异常。 - 检查
SharedPreferences初始化:部分设备在Release模式下,SharedPreferences.getInstance()可能因存储权限问题卡住,需确保应用已获取对应存储权限(targetSdk >=33时需额外处理)。
3. 检查Flutter Release编译配置
- 防止MethodChannel被混淆:在
android/app/proguard-rules.pro中添加规则,保护通道名称不被混淆:-keep class io.flutter.plugin.common.MethodChannel { *; } -keep class io.flutter.plugin.common.MethodChannel$MethodCallHandler { *; } -keep class com.example.al_muezzin.AlarmManagement { *; } // 替换为你的通道相关类 - 检查R8优化:若Kotlin通知代码被R8误删,会导致方法调用失败进而卡住应用,可暂时关闭R8测试是否恢复正常。
4. 验证闪屏与导航逻辑
- 添加初始化超时处理:防止初始化卡住导致应用无法启动:
void main() async { WidgetsFlutterBinding.ensureInitialized(); // 超时处理,避免初始化无限阻塞 await initialServices().timeout(Duration(seconds: 5), onTimeout: () { print('Services init timed out'); }); timeago.setLocaleMessages('ar', timeago.ArMessages()); runApp(const MyApp()); } - 检查
InitialBindings逻辑:若InitialBindings依赖未初始化完成的服务,Release模式下异步顺序问题可能导致页面无法加载。
5. 最小化复现测试
- 暂时移除Kotlin通知相关代码,重新打包Release版本,若应用恢复正常,说明问题出在原生通知代码中,再逐步添加代码定位具体出错点。
- 单独测试MethodChannel调用:先不调用
setNextAlarm,看Release模式下应用能否正常启动,再逐步加入该方法排查是否是调用导致的阻塞。
内容的提问来源于stack exchange,提问作者ahmed albakor
相关产品推荐
相关产品推荐

