Android 使用androidx.widget.Toolbar实现选项菜单首次打开延迟如何解决
问题原因
- 懒加载机制:Toolbar的弹出菜单默认采用懒加载逻辑,只有首次点击溢出按钮时,系统才会执行菜单布局解析、主题资源加载、动画配置初始化等操作,这些IO和渲染操作会造成数十到数百毫秒的延迟,低配置设备上延迟会更高。
- 主题不匹配:你当前Toolbar使用的是
ThemeOverlay.MaterialComponents.Dark.ActionBar主题,但弹出菜单的popupTheme指定的是 AppCompat 系列的ThemeOverlay.AppCompat.Light,两个主题体系不兼容,系统首次渲染菜单时需要做额外的适配转换,额外增加耗时。 - 多余资源加载:你三个菜单项都配置了icon属性,首次加载时需要额外解析drawable资源,也会增加少量耗时,如果不需要显示菜单项图标可以去掉该属性。
- 代码笔误:你
onCreateOptionsMenu中加载的菜单是R.menu.menu,但你提供的菜单文件名为appbar_menu.xml,资源ID不匹配也可能导致首次加载时的资源查找耗时。
优化方案
1. 修正基础配置问题
首先把onCreateOptionsMenu中的菜单加载代码改为对应你的菜单文件名,同时补充Toolbar绑定逻辑:
package com.test.test_option_menu; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.Menu; import android.view.MenuInflater; import android.widget.PopupMenu; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; public class MainActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 绑定Toolbar到Activity Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); // 预加载菜单资源,主线程空闲时执行 new Handler(Looper.getMainLooper()).post(() -> { PopupMenu dummyPopup = new PopupMenu(this, toolbar); dummyPopup.getMenuInflater().inflate(R.menu.appbar_menu, dummyPopup.getMenu()); }); } public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); // 修正菜单资源ID inflater.inflate(R.menu.appbar_menu, menu); return true; } }
上面的代码已经加入了预加载逻辑,会在主线程空闲时提前初始化PopupMenu实例,完成布局和资源的加载,首次点击时直接复用已经加载好的资源,延迟会大幅降低。
2. 统一主题配置
把Toolbar的popupTheme替换为和MaterialComponents配套的主题,避免主题适配耗时,修改activity_main.xml中的Toolbar配置:
<androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" app:layout_constraintTop_toTopOf="parent" <!-- 修改为配套的MaterialComponents主题 --> app:popupTheme="@style/ThemeOverlay.MaterialComponents.Light" app:title="Quran" app:titleTextAppearance="@style/Toolbar.TitleText" app:titleTextColor="?attr/colorOnPrimary"> </androidx.appcompat.widget.Toolbar>
3. 自定义弹出动画时长(可选)
如果需要进一步加快弹出速度,可以自定义动画缩短时长:
首先在res/values/styles.xml中添加自定义弹出主题:
<style name="FastPopupOverlay" parent="ThemeOverlay.MaterialComponents.Light"> <item name="android:popupAnimationStyle">@style/FastPopupAnim</item> <!-- 不需要动画的话可以直接设为@null,菜单会直接弹出 --> <!-- <item name="android:popupAnimationStyle">@null</item> --> </style> <style name="FastPopupAnim"> <item name="android:windowEnterAnimation">@anim/fast_fade_in</item> <item name="android:windowExitAnimation">@anim/fast_fade_out</item> </style>
新建res/anim/fast_fade_in.xml:
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="60" android:fromAlpha="0" android:toAlpha="1" />
新建res/anim/fast_fade_out.xml:
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="50" android:fromAlpha="1" android:toAlpha="0" />
最后把Toolbar的popupTheme修改为自定义主题即可:
app:popupTheme="@style/FastPopupOverlay"
内容的提问来源于stack exchange,提问作者Umar Alfaruq
相关产品推荐
相关产品推荐

