我目前正在开发一个Android项目,其目标是录制音频并实时显示频谱图。我的设计包含三个主题:
这个图表应该或多或少地显示它应该如何工作
Start
UI |-•-------------•----------•------•----------•------•----------•--
\ / \ / / \ / / \ /
\ / \ / / \ / / \ /
Ana \ / |----| / |----| / |----| ...
\ / / /
\ / / /
Rec |---•-•-----------------•-----------------•--------------------
Notify Notify Notify
为清楚起见,让我解释一下这是如何工作的。一开始,UI线程启动记录器线程。使用AudioRecord.setRecordPositionUpdateListener - 方法,定期通知主线程上的侦听器。该侦听器启动一个新线程进行分析。结果将返回到主线程,主线程使用AndroidPlot显示结果。
请注意,分析是低级写入的,因此分析帧所需的时间不会超过帧本身的长度。这意味着可以在必须分析新帧之前对帧进行分析。
更准确地说,我正在使用AsyncTask来解决所有这些问题。管理AudioRecord的类是AsyncTask,OnRecordPositionUpdateListener调用publishProgress返回主线程。在onProgressUpdate方法中,创建了一个扩展AsyncTask的AnalysisTask类的对象。分析结果使用get() - 方法收集并显示在UI线程中。
可悲的是,它并没有像预期的那样顺利。出现了许多问题:
1)GUI上有一个停止按钮。由于未阻止UI线程,因此用户应该能够使用它来停止该过程。但是当它被按下时,程序似乎冻结,并最终崩溃("application not responding")。
2)日志告诉我,在记录器线程上的通知和UI线程上的分析调用之间有很多时间。它甚至需要很长时间才会发生另一次通知。这会导致数据堆积,最终导致OutOfMemory错误。
3)当结果返回主线程时,redraw() - 调用与屏幕上图形的实际外观之间有很多时间。
鉴于处理器是单核的,大多数问题都可以通过线程的调度来解释,对吧?在这种情况下,它们是由于记录器线程非常繁忙导致UI线程调度得太晚,从而导致到达队列的任务与实际执行的任务之间出现延迟。
有没有办法解决这个问题?我可以阻止记录器线程占用所有CPU电源,而不会丢失帧或通知UI线程的规则性吗?我尝试了Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
但没有结果。
谢谢!