flutter-startup-gate
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFlutter startup gate
Flutter 启动闸门
Stop startup crashes where the UI reads a field before an async has assigned it. The fix is a gate in the root widget: render a splash until , an error screen with retry when init fails, and the app shell only after.
lateinit()initialized解决UI在异步完成赋值前读取字段导致的启动崩溃问题。解决方案是在根组件中添加一个闸门:完成初始化前显示启动页,初始化失败时显示带重试按钮的错误页面,仅在初始化完成后显示应用外壳。
init()lateSteps
步骤
- Confirm the race. The crash (or similar) means a widget read a
LateInitializationError: Field 'repo' has not been initializedfield in the first frame, beforelate's awaits finished. It may pass on a fast host and only crash on slow real devices — checkinit()forlogcaton-device.E/flutter - Add an init gate to the root widget ():
app.dart- While → show a splash (logo + spinner + "Opening…").
initializing - If → show an error screen with a Retry button (do not crash).
error != null - Only when → show the app shell. Completion criterion: every first-frame widget sits behind the gate; none touch
initialized/services before the gate opens.repo
- While
- Guard against double-init. Add a flag so
_initStartedcan't run twice (hot reload / retry). Exposeinit()that resets state and re-runsretryInit(). Completion criterion: tapping Retry re-runs init and reaches the shell without a second manual launch.init() - Verify. clean;
flutter analyzepasses; reinstall on the real device and confirm logcat shows noflutter teston cold start (seeLateInitializationError).flutter-device-smoke-test
- 确认竞争条件:崩溃信息(或类似信息)表示组件在第一帧就读取了
LateInitializationError: Field 'repo' has not been initialized字段,而此时late中的await操作尚未完成。该问题在性能较好的主机上可能不会出现,仅在性能较慢的真实设备上崩溃——请查看设备上的init()中的logcat日志。E/flutter - 给根组件()添加初始化闸门:
app.dart- 当状态时 → 显示启动页(Logo + 加载动画 + “正在启动…”)。
initializing - 如果→ 显示带重试按钮的错误页面(不要崩溃)。
error != null - 仅当状态时 → 显示应用外壳。 完成标准:所有首帧组件都处于闸门之后;在闸门打开前,没有组件会访问
initialized/服务。repo
- 当
- 防止重复初始化:添加标志,确保
_initStarted不会运行两次(热重载/重试场景)。暴露init()方法,用于重置状态并重新运行retryInit()。 完成标准:点击重试按钮会重新执行初始化流程,并无需手动重启应用即可进入应用外壳。init() - 验证:无问题;
flutter analyze测试通过;在真实设备上重新安装应用,确认冷启动时flutter test中没有logcat信息(可参考LateInitializationError)。flutter-device-smoke-test
Reference
参考信息
- Root cause pattern: is async (opens SQLite, wires services, assigns
AppState.init()fields);latebuilds and screens callMaterialAppinapp.repo...before the first await resolves.build() - The gate doubles as a user-visible loading state and an error boundary — both needed on slow devices.
- 根本原因模式:是异步方法(打开SQLite数据库、连接服务、为
AppState.init()字段赋值);late进行构建,且页面在第一个await操作完成前就在MaterialApp方法中调用build()。app.repo... - 该闸门同时兼具用户可见的加载状态和错误边界的功能——这两者在性能较慢的设备上都是必需的。