You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中release模式下moveNext()函数不执行,debug模式正常

Flutter Release模式下initState中moveNext()函数失效问题

Debug模式下页面加载动画正常,initState内调用的moveNext()可完成页面跳转;切换到Release模式后,moveNext()完全无法执行。已排查AndroidManifest配置,添加了必要权限,相关代码如下:

Dart代码

class _MainAppState extends State<MainApp> {
  @override
  void dispose() {
    super.dispose();
  }

  @override
  void initState() {
    moveNext();
    _initializeFirebase();
    super.initState();
  }

  Future<bool> _onWillPop() async {
    if (currentPage.length == 1) {
      return (await showDialog(
            context: context,
            builder: (context) => AlertDialog(
              title: Text('Are you sure?'),
              content: Text('Do you want to exit'),
              actions: <Widget>[
                TextButton(
                  onPressed: () => Navigator.of(context).pop(false),
                  child: Text('No'),
                ),
                TextButton(
                  onPressed: () => Navigator.of(context).pop(true),
                  child: Text('Yes'),
                ),
              ],
            ),
          )) ??
          false;
    } else {
      Navigation.pop(context);
      Navigator.pushReplacement(context,
          MaterialPageRoute(builder: (BuildContext context) => MainApp()));
      return false;
    }
  }

  void moveNext() async {
    var prefs = await SharedPreferences.getInstance();
    if (!noMove) {
      bool connected = await InternetConnectionChecker().hasConnection;
      bool? logIn = true;
      if (forceLogOut) {
        logIn = false;
      } else {
        if (auth.currentUser != null) {
          logIn = true;
        } else {
          logIn = prefs.getBool("isLoggedIn");
        }
      }

      if (connected) {
        Future.delayed(Duration(seconds: 1), () async {
          setState(() {
            internetConnected = true;
          });
          if (!forceHomeScreen) {
            if (logIn != null) {
              if (logIn) {
                Future.delayed(Duration(milliseconds: 2000), () async {
                  setState(() {
                    Navigation.pushReplace(context, homePage);
                    setState(() {});
                  });
                });
                await AppAPI().getCurrentUser();
                await AppAPI().getData();
                setState(() {});
              } else {
                Future.delayed(Duration(milliseconds: 2000), () {
                  setState(() {
                    Navigation.pushReplace(context, Welcome());
                    forceLogOut = false;
                  });
                });
              }
            } else {
              Future.delayed(Duration(milliseconds: 2000), () {
                setState(() {
                  forceLogOut = false;
                  Navigation.pushReplace(context, Welcome());
                  setState(() {});
                });
              });
            }
          } else {
            setState(() {
              Navigation.pushReplace(context, homePage);
              setState(() {});
            });
          }
        });
      } else {
        Future.delayed(Duration(seconds: 2), () {
          setState(() {
            internetConnected = false;
            Navigation.pushReplace(context, NoInternet());
            setState(() {});
          });
        });
      }
    } else {
      Future.delayed(Duration(seconds: 2));
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: _onWillPop,
        child: MaterialApp(
            debugShowCheckedModeBanner: false, home: currentPage.last));
  }
}

AndroidManifest.xml代码

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>


    <application
        android:label="ThePhotographers"
        android:name="${applicationName}"
        android:icon="@mipmap/launcher_icon">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

解决方法

1. 捕获异步异常

Release模式下异步错误会静默失败,给moveNext()添加try-catch捕获异常,便于排查问题:

void moveNext() async {
  try {
    var prefs = await SharedPreferences.getInstance();
    // 原函数逻辑
  } catch (e, stackTrace) {
    print('moveNext执行异常: $e\n$stackTrace');
    // 可选:添加错误 fallback 逻辑,比如跳转到欢迎页
  }
}

2. 调整Firebase初始化顺序

当前initState先执行moveNext()再初始化Firebase,Release模式下auth.currentUser可能未就绪,导致逻辑错误。修改顺序确保Firebase初始化完成后再执行moveNext():

@override
void initState() {
  super.initState();
  _initializeFirebase().then((_) {
    moveNext();
  });
}

3. 处理SharedPreferences空值

prefs.getBool("isLoggedIn")可能返回null,给logIn设置默认值避免分支逻辑异常:

logIn = prefs.getBool("isLoggedIn") ?? false;

4. 简化异步流程

嵌套的Future.delayed和setState可能导致Release模式下UI线程阻塞,改用顺序await简化逻辑:

if (connected) {
  await Future.delayed(Duration(seconds: 1));
  setState(() => internetConnected = true);
  
  if (!forceHomeScreen) {
    await Future.delayed(Duration(milliseconds: 2000));
    final shouldLogin = logIn ?? false;
    if (shouldLogin) {
      await AppAPI().getCurrentUser();
      await AppAPI().getData();
      Navigation.pushReplace(context, homePage);
    } else {
      Navigation.pushReplace(context, Welcome());
      setState(() => forceLogOut = false);
    }
  } else {
    Navigation.pushReplace(context, homePage);
  }
} else {
  await Future.delayed(Duration(seconds: 2));
  setState(() => internetConnected = false);
  Navigation.pushReplace(context, NoInternet());
}

5. 添加混淆规则

Release模式代码混淆可能导致第三方库(如SharedPreferences、Firebase)失效,在android/app/proguard-rules.pro中添加规则:

# 保留SharedPreferences相关类
-keep class android.content.SharedPreferences { *; }
-keep class android.content.SharedPreferences$Editor { *; }

# 保留Firebase Auth类
-keep class com.google.firebase.auth.** { *; }

# 保留网络检测相关类
-keep class java.net.InetAddress { *; }

内容的提问来源于stack exchange,提问作者CodeVault

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 03:24:57