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