使用EventBus更新Android Auto屏幕触发IllegalStateException问题
Android Auto中EventBus更新状态后界面不渲染且抛出IllegalStateException的修复方案
问题场景
尝试通过EventBus更新Android Auto屏幕状态并重新渲染,编写了CarPlayScreen代码后,初始模板可正常显示,但触发onCapsuleStateUpdate方法后界面未更新,同时控制台抛出异常。
原代码
package com.capsule import androidx.car.app.CarContext import androidx.car.app.Screen import androidx.car.app.model.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode class CarPlayScreen(carContext: CarContext) : Screen(carContext) { private var template: Template private var eventBus = EventBus.getDefault() @Subscribe(threadMode = ThreadMode.MAIN) fun onCapsuleStateUpdate(state: CapsuleState) { template = GridTemplate.Builder() .setTitle("Temperature: ${state.temperature}C") .build() } init { eventBus.register(this) val row = Row.Builder() .setTitle("Wait state update") .build() val pane = Pane.Builder() .addRow(row) .build() template = PaneTemplate.Builder(pane) .setHeaderAction(Action.APP_ICON) .build() invalidate() } override fun onGetTemplate(): Template { return template } }
错误日志
E Could not dispatch event: class com.capsule.CapsuleState to subscribing class class com.capsule.CarPlayScreen java.lang.IllegalStateException: Template is in a loading state but lists are added, or vice versa at androidx.car.app.model.GridTemplate$Builder.build(GridTemplate.java:282) at com.capsule.CarPlayScreen.onCapsuleStateUpdate(CarPlayScreen.kt:24) at java.lang.reflect.Method.invoke(Native Method) at org.greenrobot.eventbus.EventBus.invokeSubscriber(EventBus.java:517) at org.greenrobot.eventbus.EventBus.postToSubscription(EventBus.java:444) at org.greenrobot.eventbus.EventBus.postSingleEventForEventType(EventBus.java:421) at org.greenrobot.eventbus.EventBus.postSingleEvent(EventBus.java:394) at org.greenrobot.eventbus.EventBus.post(EventBus.java:275) at com.capsule.CapsuleBleManager.followState$lambda$10(CapsuleBleManager.kt:190) at com.capsule.CapsuleBleManager.$r8$lambda$6x0OdCCBxFndfQ6AFD4N11VDXro(Unknown Source:0) at com.capsule.CapsuleBleManager$$ExternalSyntheticLambda0.onDataReceived(Unknown Source:2) at no.nordicsemi.android.ble.ValueChangedCallback.lambda$notifyValueChanged$0(ValueChangedCallback.java:184) at no.nordicsemi.android.ble.ValueChangedCallback$$ExternalSyntheticLambda1.run(Unknown Source:6) at android.os.Handler.handleCallback(Handler.java:914) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:224) at android.app.ActivityThread.main(ActivityThread.java:7560) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
错误提示
IllegalStateException – if the template is in a loading state but there are lists added, or vice versa, or if the template does not have either a title or header Action set.
修复方案
1. 修正GridTemplate的构建逻辑
异常核心原因是你创建的GridTemplate不符合Android Auto的模板规范:既没有添加网格内容,也没有标记为加载状态,触发了非法状态校验。
修改onCapsuleStateUpdate方法,二选一即可:
- 方案A:添加合法的网格内容
@Subscribe(threadMode = ThreadMode.MAIN) fun onCapsuleStateUpdate(state: CapsuleState) { // 创建网格项 val tempGridItem = GridItem.Builder() .setTitle("当前温度") .setText("${state.temperature}℃") .build() // 构建合法的GridTemplate template = GridTemplate.Builder() .setTitle("温度监控") .addGridItem(tempGridItem) // 必须添加至少一个网格项 .setHeaderAction(Action.APP_ICON) // 可选,保持头部动作一致性 .build() // 通知框架重新渲染 invalidate() }
- 方案B:设置加载状态(如果需要等待数据)
@Subscribe(threadMode = ThreadMode.MAIN) fun onCapsuleStateUpdate(state: CapsuleState) { template = GridTemplate.Builder() .setTitle("更新中...") .setLoading(true) // 标记为加载状态,此时不能添加网格项 .build() invalidate() }
2. 补充模板更新的关键步骤
更新template变量后,必须调用invalidate()方法,通知Android Auto框架重新获取并渲染新模板。原代码在事件回调中遗漏了这一步,这也是界面不更新的直接原因。
3. 优化EventBus生命周期管理(推荐)
为避免内存泄漏,在屏幕销毁时注销EventBus:
override fun onDestroy() { super.onDestroy() eventBus.unregister(this) }
内容的提问来源于stack exchange,提问作者Timur Ruziev
相关产品推荐
相关产品推荐

