Flutter应用切后台返回后从闪屏重启(低端设备专属问题)
Flutter应用从第三方App返回后重启(仅低端设备出现)
用户通过Flutter应用跳转至其他App(如从Razor Pay跳转到Google Pay完成支付),返回时应用未从退出位置恢复,而是从闪屏界面重新启动。该问题仅在部分低端设备出现,高端设备运行正常,导致支付回调事件无法被监听。
问题流程
- 用户发起购买操作
- 弹出Razor Pay窗口,用户选择Google Pay付款渠道
- 跳转至Google Pay完成支付
- 返回Flutter应用时,未恢复至原页面,而是从闪屏界面重新启动
对应的AndroidManifest.xml配置
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bynge.story"> <queries> <provider android:authorities="com.facebook.katana.provider.PlatformProvider" /> <!-- allows app to access Facebook app features --> </queries> <application android:label="Notion Press" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true" android:name="com.clevertap.android.sdk.Application"> <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="bynge_local_notification" /> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@mipmap/ic_launcher" /> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" /> <activity android:name=".MainActivity" 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" android:exported="true"> <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" /> <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" /> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <intent-filter> <action android:name="FLUTTER_NOTIFICATION_CLICK" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <!-- Deep Links --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="bynge" android:host="app" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="bynge" android:host="series" android:pathPrefix="/seriesid/episodeid" /> </intent-filter> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" android:host="bynge.in" android:pathPrefix="/wa" /> </intent-filter> </activity> <meta-data android:name="flutterEmbedding" android:value="2" /> <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/> <meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/> <activity android:name="com.facebook.FacebookActivity" android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:label="@string/app_name" android:exported="true"/> <activity android:name="com.facebook.CustomTabActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="@string/fb_login_protocol_scheme" /> </intent-filter> </activity> <activity android:name="com.yalantis.ucrop.UCropActivity" android:screenOrientation="portrait" android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:exported="true"/> <meta-data android:name="CLEVERTAP_BACKGROUND_SYNC" android:value="1"/> <meta-data android:name="CLEVERTAP_NOTIFICATION_ICON" android:value="ic_launcher"/> <meta-data android:name="flutterEmbedding" android:value="2" /> </application> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="com.android.vending.BILLING" /> </manifest>
解决方案
1. 调整Activity启动模式
将MainActivity的launchMode从singleTop改为singleTask,确保应用返回时复用已存在的Activity实例,避免重新创建:
android:launchMode="singleTask"
singleTask模式下,系统会保证该Activity实例唯一存在于任务栈中,从第三方App返回时直接将任务栈带到前台,不会重新启动闪屏。
2. 实现内存回收后的状态恢复
低端设备内存不足时,系统会回收后台应用进程。需在Flutter层做好状态保存:
- 在
StatefulWidget中通过saveState方法保存关键数据(如订单ID、当前路由) - 在
initState或didChangeDependencies中检查是否有保存的状态,若存在则直接恢复到对应页面和状态
3. 正确处理支付回调
- 在Android原生MainActivity中重写
onNewIntent方法,接收第三方App返回的Intent数据,并传递给Flutter:
override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) // 通过MethodChannel将支付结果传递给Flutter intent?.let { val methodChannel = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, "payment_callback") methodChannel.invokeMethod("handlePaymentResult", it.extras) } }
- 在Flutter层监听MethodChannel回调,即使应用重启,也能通过Intent数据恢复支付状态并处理结果
4. 优化内存占用
减少应用后台时的内存消耗,降低被系统回收的概率:
- 及时释放未使用的资源(如图片缓存、大对象)
- 通过
WidgetsBindingObserver监听应用生命周期,在进入后台时暂停不必要的任务、释放资源 - 避免在后台运行耗时或占用内存的操作
5. 检查第三方SDK配置
确认Razor Pay SDK的回调配置正确,避免因Intent过滤问题导致返回时启动新实例:
- 确保Razor Pay相关的Activity(若有)使用正确的启动模式
- 检查Manifest中是否正确注册了支付回调所需的Intent Filter
内容的提问来源于stack exchange,提问作者Arkaan Sayed
相关产品推荐
相关产品推荐

