You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Flutter Add to App Android启动Activity白屏问题解决方案咨询

已验证的Flutter Add to App首帧白屏解决方案

我之前在处理Flutter Add to App的项目时遇到过完全一样的白屏问题,下面给你几个经过项目验证的可行方案,你可以根据自己的需求组合使用:

方案一:透明主题+首帧就绪后显示Activity

这个方案的核心是让FlutterActivity启动时保持透明,直到Flutter首帧渲染完成后再切换回正常主题并显示窗口,彻底避免白屏:

  1. 添加透明主题
    styles.xml中新增一个透明主题,继承自你现有的AppTheme.NoFullscreen
<style name="TransparentFlutterActivityTheme" parent="AppTheme.NoFullscreen">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowIsTranslucent">true</item>
</style>
  1. 修改AndroidManifest配置
    CMFlutterActivity的主题临时设置为这个透明主题:
<activity 
    android:name=".ui.flutter.CMFlutterActivity" 
    android:theme="@style/TransparentFlutterActivityTheme" <!-- 替换成透明主题 -->
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" 
    android:hardwareAccelerated="true" 
    android:windowSoftInputMode="adjustResize" 
    android:screenOrientation="portrait" 
    android:stateNotNeeded="true" 
    android:exported="true" />
  1. 修改CMFlutterActivity代码
    重写onFlutterUiDisplayed方法,在首帧就绪后恢复正常显示:
class CMFlutterActivity : FlutterActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        // 先设置窗口flag确保透明效果
        window.setFlags(
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
        )
        super.onCreate(savedInstanceState)
    }

    override fun onFlutterUiDisplayed() {
        super.onFlutterUiDisplayed()
        // Flutter首帧渲染完成,切换回原主题
        setTheme(R.style.AppTheme_NoFullscreen)
        // 移除透明相关flag,恢复窗口正常布局
        window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
        // 确保窗口可见(如果之前被隐藏的话)
        window.decorView.visibility = View.VISIBLE
    }
}

方案二:添加占位加载页(提升用户体验)

如果觉得透明过渡不够友好,可以在FlutterView上层添加一个和App风格一致的加载页,等首帧就绪后隐藏,用户看到的是加载状态而非空白:

  1. 创建加载布局
    新建layout_loading.xml,比如包含进度条和App Logo:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@color/app_background"
    android:orientation="vertical">

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="加载中..."
        android:textColor="@color/text_primary" />
</LinearLayout>
  1. 修改CMFlutterActivity代码
    在onCreate中添加加载View,首帧就绪后隐藏:
class CMFlutterActivity : FlutterActivity() {
    private lateinit var loadingView: View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 加载自定义加载布局
        loadingView = LayoutInflater.from(this).inflate(R.layout.layout_loading, null)
        // 获取Activity根布局,添加加载View
        val rootContainer = findViewById<ViewGroup>(android.R.id.content)
        rootContainer.addView(loadingView)
    }

    override fun onFlutterUiDisplayed() {
        super.onFlutterUiDisplayed()
        // 首帧就绪,隐藏加载View
        loadingView.visibility = View.GONE
    }
}

方案三:预加载FlutterEngine(从根源减少等待时间)

如果你的App会多次启动Flutter页面,预加载FlutterEngine可以大幅缩短首帧加载时间,从根源减少白屏时长:

  1. 在Application中预初始化FlutterEngine
class MyApp : Application() {
    lateinit var preWarmedEngine: FlutterEngine

    override fun onCreate() {
        super.onCreate()
        // 初始化FlutterEngine
        preWarmedEngine = FlutterEngine(this)
        // 执行Dart入口点
        preWarmedEngine.dartExecutor.executeDartEntrypoint(
            DartExecutor.DartEntrypoint.createDefault()
        )
        // 将Engine缓存起来,供后续Activity复用
        FlutterEngineCache.getInstance().put("pre_warmed_engine", preWarmedEngine)
    }
}
  1. 在CMFlutterActivity中复用预加载的Engine
class CMFlutterActivity : FlutterActivity() {
    override fun provideFlutterEngine(context: Context): FlutterEngine? {
        // 复用预加载的FlutterEngine
        return FlutterEngineCache.getInstance().get("pre_warmed_engine")
    }
}

推荐组合

我个人推荐方案二 + 方案三的组合:预加载Engine减少等待时间,同时用加载页提升用户感知,几乎可以消除白屏带来的不良体验。

内容的提问来源于stack exchange,提问作者Leonardo da Silva

火山引擎 最新活动