在可运行任务 [android] 中处理 while 循环时,处理程序冻结 UI

Handler freezes UI when processing while loop inside a runnable task [android]

我要重复- - -...等等。 当其能量达到某个阈值并播放时,录音(几秒钟)停止。播放后,开始新的录音。所以我必须使用缓冲区监控能量并在播放时间计算后开始新的记录。我的伪代码(最简化的形式)如下所示:

...

public class MainActivity extends Activity {
    private Handler myHandler = new Handler();

....

    private Runnable timedTask = new Runnable() {
        public void run() {
           audiorecorder = new AudioRecord(...  initializes
           audiorecorder.startRecording();
           isRecording = true; 
           ElapsedTime = 0.0;
           while(true) {
                ReadByte = audiorecorder.read(buffer, 0, buffersize);
                // Write ReadByte onto file (temp.pcm)

                EnergyBuffer = <some averaged energy over a period (1 sec or so)>
                if(EnergyBuffer > Threshold)
                     break;
                ElapsedTime = ...
           }
           // audiorecorder.release, stop, and null
           // play temp.pcm using AudioTrack           

           myHandler.postDelayed(timedTask, Elapsedtime);
    };
}

这是由启动和停止按钮触发的,如下所示,

    StartButton.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {
            myHandler.post(timedTask);
        }
    });

    StopButton.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {
            myHandler.removeCallbacks(timedTask);
        }
    });

问题是在录音或播放时,没有按钮起作用,我必须等到它完成录音。如何防止冻结录制?仅仅是因为whileloop吗?请帮助..!

如果我运行如下,没有错误。

Thread t = new Thread(timedTask);
t.start();

这只是一次性的,但是之后当处理程序延迟执行时,它也会冻结 UI。

处理程序 posts 运行nable 任务进入线程中的循环程序。它不会自行创建一个新线程,在该线程上 运行 运行 异步启用。

当您通过调用构造函数new Handler()创建处理程序时,处理程序将默认获取调用构造函数的当前线程的循环程序。由于您在 UI 线程上调用了 new Handler(),任何给予处理程序 post 命令的 运行nable 都将被添加到 UI 线程。

您需要创建一个新线程并获取它的循环器,方法是

HandlerThread readThread = new HandlerThread("");
readThread.start();
myHandler = new Handler(readThread.getLooper());

HandlerThread 是一个线程,它会自动设置一个 looper 供您使用。

当然,你也需要在不需要的时候退出线程

readThread.quit();

你真是个天才,工作起来很有魅力,这正是我工作了几天的原因,非常感谢你!! 这是我的问题的答案:

public class MainActivity extends Activity {
    private Handler myHandler;

....

    private Runnable timedTask = new Runnable() {
        public void run() {
           audiorecorder = new AudioRecord(...  initializes
           audiorecorder.startRecording();
           isRecording = true; 
           ElapsedTime = 0.0;
           while(true) {
                ReadByte = audiorecorder.read(buffer, 0, buffersize);
                // Write ReadByte onto file (temp.pcm)

                EnergyBuffer = <some averaged energy over a period (1 sec or     so)>
                if(EnergyBuffer > Threshold)
                     break;
                ElapsedTime = ...
           }
           // audiorecorder.release, stop, and null
           // play temp.pcm using AudioTrack           

           myHandler.postDelayed(timedTask, Elapsedtime);
    };
....
    protected void OnCreate(Bundle savedInstanceState) {
        ...
        HandlerThread readThread = new HandlerThread("");
        readThread.start();
        myHandler = new Handler(readThread.getLooper());
        ...
    }
}