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

Android跨类获取labelString值时空指针异常致应用崩溃排查

崩溃根因

报错的空指针不是textMe字段为空,是你在CameraActivity中使用的tracker实例本身没有初始化,为null值。你在onCreate生命周期阶段直接访问tracker.textMe时,Tracker对象还未完成创建,自然会抛出空对象引用异常。

除此之外你的代码还有两个逻辑bug会导致后续就算不崩溃也拿不到正确值:

  • textMe字段是在Tracker执行识别框绘制逻辑时才会赋值的,Activity刚启动onCreate阶段,目标检测逻辑还没开始运行,就算tracker实例不为空,这个字段也没有有效值
  • 你在TTS初始化的位置就提前把speak变量赋值为当时的tracker.textMe,后续就算Tracker更新了识别结果,定时任务里读的永远是最开始拿到的旧空值,拿不到最新的labelString
修复方案

1. 优先初始化tracker实例

确保在访问tracker的任何属性之前,已经完成了Tracker对象的实例化,把初始化逻辑放到onCreate中所有访问tracker的代码之前:

// 先在CameraActivity类的成员位置声明tracker
private Tracker tracker;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);
    
    // 先初始化tracker,替换成你项目中实际的Tracker构造方法和参数
    tracker = new Tracker(/* 传入你项目要求的构造参数,比如上下文、资源等 */);
    
    // 再往下写TTS、相机相关的原有逻辑
    // ...
}

2. 动态取值加空判断,不要提前固定值

删掉onCreate里一开始写的String speak = tracker.textMe;,改成每次定时任务执行时再读取最新的识别结果,同时加多层空判断,从根源避免空指针:

mTTS = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
    @Override
    public void onInit(int status) {
        if(status == TextToSpeech.SUCCESS) {
            mTTS.setLanguage(Locale.ENGLISH);
            runnable = new Runnable() {
                @Override
                public void run() {
                    handler.postDelayed(this, 1000L);
                    String speak = "";
                    // 逐层判空
                    if (tracker != null && !TextUtils.isEmpty(tracker.textMe)) {
                        speak = tracker.textMe;
                        Toast.makeText(CameraActivity.this, speak, Toast.LENGTH_SHORT).show();
                        mTTS.speak(speak, TextToSpeech.QUEUE_FLUSH, null);
                    }
                }
            };
            handler.post(runnable);
            // 删掉你原来重复写的第二遍handler.post(runnable); 否则会启动两个重复的定时任务
        } else {
            Toast.makeText(CameraActivity.this, "Error", Toast.LENGTH_SHORT).show();
        }
    }
});

3. 修正Tracker类的textMe字段声明

在Tracker类的成员变量位置声明textMe,给默认初始值,加volatile保证多线程读取的可见性,避免字段未初始化、多线程值不同步的问题:

// Tracker类成员位置添加
public volatile String textMe = "";

如果你的识别逻辑存在trackedObjects为空、循环不执行的场景,可以根据业务需求决定是清空textMe还是保留上一次识别结果,避免读到过期值。

额外说明

日志末尾的A resource failed to call close警告属于资源未释放问题,和本次空指针崩溃无关,后续可以排查下相机流、文件流、TTS资源的关闭逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 09:30:54