Flutter鉴权加载时显示flutter_native_splash解决启动页黑屏
GetX 结合 flutter_native_splash 无黑屏鉴权跳转实现方案
核心逻辑:将原生启动页的移除时机和鉴权状态强绑定,彻底移除自定义Flutter启动页,从根源规避首帧衔接黑屏问题,具体改造步骤如下:
1. 调整main函数初始化逻辑
删掉runApp之后立刻执行FlutterNativeSplash.remove()的代码,保留原生启动页直到鉴权流程完成:
void main() async { // 保留原有初始化绑定逻辑 final widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); // 保留原生启动页的逻辑不动 FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); // 原有依赖注入逻辑不变,完成AuthService、AuthController等服务的注册 await internalInitialized(); // 直接启动应用,不要在此处移除原生启动页 runApp(const MyApp()); }
2. 改造AuthController,绑定启动页移除时机
在鉴权状态的监听回调里处理原生启动页的移除,加标记位防止重复调用,仅在第一次拿到明确鉴权结果(已登录/未登录)时移除启动页:
enum AuthStatus { authenticationLoading, authenticated, unauthenticated } class AuthController extends ConnectivityController { // 标记位:防止后续登录登出操作重复触发启动页移除 bool _nativeSplashRemoved = false; final Rx<AuthStatus> authStatus = AuthStatus.authenticationLoading.obs; @override void onInit() { super.onInit(); // 永久监听鉴权状态变化 ever(authStatus, (currentStatus) { // 仅当鉴权出明确结果、且原生启动页未被移除时执行移除操作 if (!_nativeSplashRemoved && currentStatus != AuthStatus.authenticationLoading) { FlutterNativeSplash.remove(); _nativeSplashRemoved = true; } }); // 原有自动登录逻辑保留,鉴权流程严格遵循状态流转 getAuthenticatedUser(); } // 原有getAuthenticatedUser、登录、登出方法逻辑保持不变: // 所有鉴权相关操作发起前,先将状态更新为authenticationLoading // 接口返回结果后,再根据鉴权结果更新为authenticated或unauthenticated }
3. 简化MyApp的页面渲染逻辑
删掉原有的自定义SplashScreen组件,鉴权加载状态下原生启动页始终覆盖在Flutter渲染层之上,Flutter层只需要返回极简占位组件避免布局报错即可,不需要做任何加载UI:
class MyApp extends GetWidget<AuthController> { const MyApp({super.key}); @override Widget build(BuildContext context) { return GetMaterialApp( // 原有主题、路由、国际化等配置全部保留 home: Obx(() { switch (controller.authStatus.value) { case AuthStatus.authenticated: return const HomeScreen(); case AuthStatus.unauthenticated: return const SignInScreen(); case AuthStatus.authenticationLoading: // 原生启动页覆盖期间,返回空占位即可 return const SizedBox.shrink(); } }), ); } }
注意事项
- 所有涉及鉴权状态变更的逻辑必须严格遵守状态流转规则,禁止跳过loading状态直接更新终态,避免原生启动页提前或延后移除
- 标记位
_nativeSplashRemoved不可省略,后续手动登录、登出操作会再次将状态切为loading,此时原生启动页早已移除,重复调用remove方法会触发异常 - 如果需要接入引导页、隐私协议弹窗等首屏逻辑,只需要在Obx的状态判断里增加对应分支即可,第一次鉴权完成后原生启动页就会移除,后续页面跳转走正常Flutter路由逻辑不受影响
- 改造完成后首帧会直接渲染最终目标页面(首页/登录页),完全跳过Flutter层自定义启动页的渲染环节,不会出现原生页和Flutter页衔接的短暂黑屏问题
内容的提问来源于stack exchange,提问作者BOOM
相关产品推荐
相关产品推荐

