Android NullPointerException第二次在Runnable中运行

Android NullPointerException第二次在Runnable中运行,android,multithreading,Android,Multithreading,我确信这个错误是因为我不完全理解线程,但现在它来了 我有一个runnable,当在方法中调用onCreate()时启动: @Override protected void onCreate(Bundle savedInstanceState) { //Set all app specific starting points here super.onCreate(savedInstanceState); setContentView(R.layout.activity_a

我确信这个错误是因为我不完全理解线程,但现在它来了

我有一个runnable,当在方法中调用
onCreate()
时启动:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //Set all app specific starting points here
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_avatar);
    ...
    soundMeterLoop();
}  

public void soundMeterLoop() {
    Log.d("SpeechKit", "Start Sound Meter");
    soundMeterHandler = new Handler();
    soundMeterRunnable = new Runnable() {
        @Override
        public void run() {
            if(!soundMeter.SoundMeterRunning) {
                Log.d("SpeechKit", "Start SoundMeter in the runnable");
                startSoundMeter();
            }
            if (soundMeter.mMediaRecorder != null) {
                amplitude = soundMeter.getAmplitude();
                decibelLevelOutput.setText("" + amplitude);
                if (amplitude > threshold) {
                    decibelLevelOutput.setTextColor(Color.RED);
                    Log.d("SpeechKit", "Interrupt and run startNuance()");
                    startNuance();
                } else {
                    decibelLevelOutput.setTextColor(Color.BLACK);
                    Log.d("SpeechKit", "Running");
                    soundMeterHandler.postDelayed(this, 100);
                }
            }

        }
    };
    soundMeterHandler.postDelayed(soundMeterRunnable, 100);
}
onCreate
中创建时,它运行正常。如您所见,它会自行终止(如果语句失败,则不更新循环),并运行
startNuance()

public void startNuance() {
    soundMeterHandler.removeCallbacksAndMessages(soundMeterRunnable);
    nuance.toggleReco();
}
然后我杀死runnable并在另一个类中启动一个方法。这个类运行良好,然后当它完成它的工作时,我使用
avatar.stopNuance()调用这个主类

这在Nuance.java类中

    @Override
    public void onFinishedRecording(Transaction transaction) {
        Log.d("SpeechKit", "onFinishedRecording");
        //We have finished recording the users voice.
        //We should update our state and stop polling their volume.
        state = State.PROCESSING;
        stopAudioLevelPoll();
        avatar.stopNuance();  // <<<<<
    }
然后它尝试运行以前的相同循环。只是这一次,我得到了很多与NullPointerException相关的错误。特别是从
decibelLevelOutput.setText(“+振幅”)开始


我不知道为什么这些东西是空的,或者如何修复它们。这是因为它启动了一个在创建runnable时没有启动的新线程吗?

您不希望每次调用
soundMeterLoop()
时都创建一个新的runnable

试试这个:

private final Handler soundMeterHandler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
    //Set all app specific starting points here
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_avatar);
    ...
    soundMeterLoop();
}  

public void soundMeterLoop() {
    Log.d("SpeechKit", "Start Sound Meter");
    soundMeterHandler.postDelayed(soundMeterRunnable, 100);
}

private final Runnable soundMeterRunnable = new Runnable() {
        @Override
        public void run() {
            if(!soundMeter.SoundMeterRunning) {
                Log.d("SpeechKit", "Start SoundMeter in the runnable");
                startSoundMeter();
            }
            if (soundMeter.mMediaRecorder != null) {
                amplitude = soundMeter.getAmplitude();
                decibelLevelOutput.setText("" + amplitude);
                if (amplitude > threshold) {
                    decibelLevelOutput.setTextColor(Color.RED);
                    Log.d("SpeechKit", "Interrupt and run startNuance()");
                    startNuance();
                } else {
                    decibelLevelOutput.setTextColor(Color.BLACK);
                    Log.d("SpeechKit", "Running");
                    soundMeterHandler.postDelayed(this, 100);
                }
            }

        }
    };

在聊天之后,实际问题出现在代码库的其他地方

问题是:

public class Nuance {

      private Activity activity;
      private Session session;
      public Avatar avatarActivity = new Avatar(); // DONT DO THIS

 ....

         @Override
         public void onFinishedRecording(Transaction transaction) {
             Log.d("SpeechKit", "onFinishedRecording");
             //We have finished recording the users voice.
              //We should update our state and stop polling their volume.
              state = State.PROCESSING;
              stopAudioLevelPoll();
             avatarActivity.stopNuance();
          }
你永远不应该创建自己的活动实例。他们受到系统的信任和管理。系统将调用实例上的生命周期方法(
onCreate
etc),但如果创建实例,则不会调用这些方法,因此会发生许多奇怪的行为

解决方法如下:

public class Nuance {

      private Avatar activity;
      private Session session;

 ....

         @Override
         public void onFinishedRecording(Transaction transaction) {
             Log.d("SpeechKit", "onFinishedRecording");
             //We have finished recording the users voice.
              //We should update our state and stop polling their volume.
              state = State.PROCESSING;
              stopAudioLevelPoll();
              activity.stopNuance();
          }

变量的类型是什么?我还想将
avatar
重命名为
avatarActivity
,这样你与
nuance
交流的内容就更明显地引用了类
nuance
。这是一个很好的电话avatarActivity@ntgCleaner我真的很想现在就开始工作!hahaI收到一个
运行时异常
无法启动活动
,还有
java.lang.NullPointerException:尝试调用虚拟方法
。源于
soundMeterHandler.postDelayed(soundMeterRunnable,100)我没有建立处理程序,我想你看到了吗?我把处理程序移到了
onCreate
上面,并使其成为finalWoops,一定滚动得太快了!我在注释后添加了一个
newhandler()
,但它似乎不起作用,然后添加了
final
,但它仍然不起作用;似乎不起作用,但现在是因为另一个问题。
分贝电平输出
为空!我在类中实例化了它,然后在循环之前在
onCreate
中初始化了它,这让我觉得您的示例非常像您的真实代码:-)在示例中,我希望在调用
soundMeterLoop()
之前实例化所有视图(
decibelLevelOutput
)(示例中的最后一行是
onCreate
)非常感谢您的关注!您为我节省了可能几天的研究时间!也感谢您的课程。每天学习!
public class Nuance {

      private Avatar activity;
      private Session session;

 ....

         @Override
         public void onFinishedRecording(Transaction transaction) {
             Log.d("SpeechKit", "onFinishedRecording");
             //We have finished recording the users voice.
              //We should update our state and stop polling their volume.
              state = State.PROCESSING;
              stopAudioLevelPoll();
              activity.stopNuance();
          }