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

Android 5竖屏应用进入最近任务并旋转时崩溃求助

这个问题我之前也遇到过,是Android 5.0(API 21)系统的一个小bug导致的!让我给你拆解一下原因和解决办法:

问题根源

虽然你已经把所有Activity设置为竖屏(android:screenOrientation="portrait"),但当设备开启自动旋转且应用进入后台后,系统依然会向Activity发送配置变更事件。而在Android 5.0中,ActionMenuView在后台状态下,它内部的ActionMenuPresenter可能已经被销毁置为null,此时系统调用onConfigurationChanged时就会触发空指针异常,也就是你看到的NullPointerException在ActionMenuPresenter.updateMenuView方法上。

解决方案

这里有几个可靠的解决办法,你可以根据自己的项目情况选择:

方法一:自定义安全版的ActionMenuView

通过继承ActionMenuView,重写onConfigurationChanged方法,先检查内部的Presenter是否为空,再执行父类逻辑,避免NPE:

class SafeActionMenuView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ActionMenuView(context, attrs, defStyleAttr) {

    override fun onConfigurationChanged(newConfig: Configuration?) {
        try {
            // 通过反射获取内部的mPresenter字段,判断是否为空
            val presenterField = ActionMenuView::class.java.getDeclaredField("mPresenter")
            presenterField.isAccessible = true
            val presenter = presenterField.get(this)
            
            if (presenter != null) {
                super.onConfigurationChanged(newConfig)
            }
        } catch (e: Exception) {
            // 反射失败时降级执行父类方法
            super.onConfigurationChanged(newConfig)
        }
    }
}

之后,你需要把布局中使用的ActionMenuView替换成这个自定义类。如果是使用Toolbar,可以在自定义Toolbar中引用这个SafeActionMenuView,或者直接替换系统默认的ActionMenuView。

方法二:在销毁OptionsMenu时清空ActionView

针对API 21单独处理,在onDestroyOptionsMenu中把自定义的ActionView置为null,避免后台时出现无效引用:

private var mainMenu: Menu? = null

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    super.onCreateOptionsMenu(menu)
    menuInflater.inflate(R.menu.menu_mainpages, menu)
    mainMenu = menu // 保存Menu引用
    
    val menuItem = menu.getItem(0)
    val profilePictureView = LayoutInflater.from(this)
        .inflate(R.layout.profile_image_layout, coordinator_main, false)
    menuItem?.actionView = profilePictureView
    
    return true
}

override fun onDestroyOptionsMenu() {
    super.onDestroyOptionsMenu()
    // 仅在Android 5.0上处理
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
        mainMenu?.getItem(0)?.actionView = null
    }
}

方法三:阻止系统发送不必要的配置变更

在AndroidManifest.xml中给Activity添加configChanges属性,让系统不重建Activity,而是直接调用onConfigurationChanged,同时强制保持竖屏:

<activity
    android:name=".MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="orientation|screenSize">

然后在Activity中重写onConfigurationChanged:

override fun onConfigurationChanged(newConfig: Configuration) {
    // 强制锁定为竖屏,忽略系统的旋转事件
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    super.onConfigurationChanged(newConfig)
}

推荐选择

我个人更推荐方法一或者方法二,因为方法三虽然简单,但如果你的应用后续需要处理其他配置变更(比如语言切换),可能会有冲突。方法一从View层面解决问题,一劳永逸;方法二则是针对特定场景的快速修复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:34:17