首次打开App时自定义Splash Screen重复加载问题求助
问题:首次安装打开App时自定义启动页加载两次,仅首次进入引导页时出现
问题背景
我通过在themes.xml中添加以下代码禁用了默认Splash Screen:
<item name="android:windowIsTranslucent">true</item>
实现自定义Splash Screen后遇到异常:首次安装打开App时启动页加载两次,后续打开正常,且仅首次进入引导页(onBoarding)时出现该问题。
相关代码
SplashScreenActivity核心代码
Thread thread = new Thread(){ public void run(){ try{ sleep(4000); onBoardingScreen = getSharedPreferences("onBoardingScreen", MODE_PRIVATE); boolean isFirstTime = onBoardingScreen.getBoolean("firstTime", true); if(isFirstTime) { SharedPreferences.Editor editor = onBoardingScreen.edit(); editor.putBoolean("firstTime",false); editor.apply(); Intent intent = new Intent(SplashScreen.this, onBoarding.class); startActivity(intent); finish(); } else { Intent intent = new Intent(SplashScreen.this, MainActivity.class); startActivity(intent); finish(); } }catch(Exception e){ } } }; thread.start();
OnBoardingActivity核心代码
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_on_boarding); //Hooks viewPager = findViewById(R.id.slider); dotsLayout = findViewById(R.id.dots); letsGetStarted = findViewById(R.id.get_started_btn); next_btn = findViewById(R.id.next_btn); if (getActionBar() != null) { getActionBar().hide(); } letsGetStarted.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(onBoarding.this, MainActivity.class); startActivity(intent); } }); //Call adapter sliderAdapter = new sliderAdapter(this); viewPager.setAdapter(sliderAdapter); //Dots addDots(0); viewPager.addOnPageChangeListener(changeListener); }
原因分析
- 透明主题引发的启动时序冲突:设置
android:windowIsTranslucent="true"后,系统会先创建透明过渡窗口,再加载你的SplashScreenActivity。首次安装时App初始化(含SharedPreferences首次创建)耗时更长,导致透明窗口+自定义启动页的视觉叠加,看起来像是启动页加载两次。 - SharedPreferences异步提交的延迟:
editor.apply()是异步写入,首次启动时可能在SplashScreenActivity未完全finish时,OnBoarding已经启动,引发启动流程混乱。 - 硬编码线程休眠的不合理性:固定4秒延迟忽略设备性能差异,线程阻塞可能打乱Activity启动时序。
解决办法
1. 替换禁用默认启动页的主题配置
放弃android:windowIsTranslucent,为SplashScreenActivity配置专属启动主题,实现系统启动窗口与自定义页面无缝衔接:
<!-- themes.xml中添加专属主题 --> <style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@drawable/your_splash_background</item> <item name="android:windowFullscreen">true</item> </style>
将@drawable/your_splash_background替换为你自定义启动页的背景图(需与SplashScreenActivity布局背景一致),然后在AndroidManifest.xml中为SplashScreenActivity指定该主题:
<activity android:name=".SplashScreenActivity" android:theme="@style/SplashTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
其他Activity使用正常主题即可。
2. 优化SplashScreenActivity逻辑
移除Thread.sleep,改用Handler.postDelayed实现延迟,同时将apply()改为同步提交的commit()(首次启动数据量小,不会阻塞主线程):
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); new Handler(Looper.getMainLooper()).postDelayed(() -> { SharedPreferences onBoardingScreen = getSharedPreferences("onBoardingScreen", MODE_PRIVATE); boolean isFirstTime = onBoardingScreen.getBoolean("firstTime", true); Intent intent; if(isFirstTime) { SharedPreferences.Editor editor = onBoardingScreen.edit(); editor.putBoolean("firstTime", false); editor.commit(); // 同步提交确保数据写入完成 intent = new Intent(SplashScreenActivity.this, onBoarding.class); } else { intent = new Intent(SplashScreenActivity.this, MainActivity.class); } startActivity(intent); finish(); }, 2000); // 推荐设置2秒以内的延迟,适配不同设备 }
3. 优化OnBoardingActivity启动配置
在AndroidManifest.xml中为OnBoardingActivity设置合理的启动模式,避免重复启动:
<activity android:name=".onBoarding" android:launchMode="singleTop" android:theme="@style/YourNormalTheme" />
4. 验证方案
卸载App后重新安装,首次打开确认启动页仅显示一次;进入引导页后退出App,再次打开确认正常进入主页面。
内容的提问来源于stack exchange,提问作者Okashi
相关产品推荐
相关产品推荐

