第二次在Runnable中运行Android NullPointerException

时间:2016-12-30 22:32:13

标签: android multithreading

我确定这个错误是因为我没有完全理解线程,但在这里它... ...

我在方法中调用onCreate()时启动了runnable:

@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();  // <<<<<
    }

然后返回我的主要活动(avatar)并运行此stopNuance()方法:

public void stopNuance() {
    Log.d("SpeechKit", "stopNuance(), start loop again");
    soundMeterLoop();
}

然后它尝试从之前运行相同的循环。只是这一次,我收到了很多与nullpointerexceptions有关的错误。特别是从decibelLevelOutput.setText("" + amplitude);

开始

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

2 个答案:

答案 0 :(得分:1)

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

问题在于:

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();
          }

您永远不应该创建自己的Activity实例。它们由系统进行创建和管理。系统将调用实例(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();
          }

答案 1 :(得分:0)

每次调用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);
                }
            }

        }
    };