我正在尝试使用新的Lolipop Api创建一个屏幕录像机。 所以,我需要一个能够以10 fps的速度循环的快速线程。
然而,经过几次测试后,我发现了一个问题: 当我的应用程序可见时,该线程表现良好。 但是当我切换到另一个应用程序或Android主屏幕时,线程真的变慢了。 甚至没有在我的线程中执行任何操作
我认为问题来自thread.sleep方法。 我从一个活动中启动了这个帖子,我已经尝试从一个服务启动它,结果相同。 无论如何,我读到服务并不是真正的地方,因为它可以随时被系统杀死。
知道如何让我的线程保持反应吗? 或者使用线程可能不是一个好的解决方案?
以下是用于测试的线程:
/** Thread used to capture images from screen */
public class ImagesCaptureThread implements Runnable {
/** fps wanted */
private final static int _fps = 10;
/** Delay between images */
private final static int _delayBetweenImagesInMs = 1000 / _fps;
/** Date used to calculate fps */
private Date _fpsDate = null;
@Override
public void run() {
Log.i("My App", "start capturing images");
_fpsDate = new Date();
while (true) {
try {
long startProcessingTime = new Date().getTime();
long elapsedTime = new Date().getTime() - _fpsDate.getTime();
Log.i("My App", "Fps : " + ((1000 * 1.0) / elapsedTime));
_fpsDate = new Date(); // Re init date
if (!_captureStarted) { // Stop capturing
Log.i("My App", "stop capturing images");
break;
}
// TO DO : Capture image
// Calculate how many time we need to sleep before next image capture
long processingTime = new Date().getTime() - startProcessingTime;
long sleepTime = _delayBetweenImagesInMs - processingTime;
if (sleepTime > 0) {
Thread.sleep(sleepTime);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
我得到的日志:
02-17 00:39:39.291: I/My App(28012): start capturing images
02-17 00:39:39.392: I/My App(28012): Fps : 9.900990099009901
02-17 00:39:39.492: I/My App(28012): Fps : 10.0
02-17 00:39:39.592: I/My App(28012): Fps : 10.0
02-17 00:39:39.693: I/My App(28012): Fps : 9.900990099009901
02-17 00:39:39.793: I/My App(28012): Fps : 10.0
02-17 00:39:39.893: I/My App(28012): Fps : 10.0
02-17 00:39:39.994: I/My App(28012): Fps : 9.900990099009901
02-17 00:39:40.094: I/My App(28012): Fps : 10.0
02-17 00:39:40.194: I/My App(28012): Fps : 10.0
[ THIS IS WHEN I SWITCH TO ANDROID HOME SCREEN ]
02-17 00:39:42.040: I/My App(28012): Fps : 7.194244604316546
02-17 00:39:42.176: I/My App(28012): Fps : 7.407407407407407
02-17 00:39:42.312: I/My App(28012): Fps : 7.462686567164179
02-17 00:39:42.450: I/My App(28012): Fps : 7.246376811594203
02-17 00:39:42.590: I/My App(28012): Fps : 7.142857142857143
02-17 00:39:42.731: I/My App(28012): Fps : 7.142857142857143
02-17 00:39:42.867: I/My App(28012): Fps : 7.407407407407407
[ THEN I SWITCH BACK TO MY APPLICATION ]
02-17 00:39:44.731: I/My App(28012): Fps : 9.900990099009901
02-17 00:39:44.831: I/My App(28012): Fps : 10.0
02-17 00:39:44.931: I/My App(28012): Fps : 10.0
02-17 00:39:45.032: I/My App(28012): Fps : 10.0
02-17 00:39:45.131: I/My App(28012): Fps : 10.1010101010101
02-17 00:39:45.231: I/My App(28012): Fps : 10.0
02-17 00:39:46.234: I/My App(28012): stop capturing images
答案 0 :(得分:0)
我不是Android开发人员,但在我看来,操作系统并没有像你想的那样快速安排你的线程执行......事件的顺序如下:
Thread.sleep(X)
似乎Android为后台应用程序中的线程提供了更低的优先级,导致在线程执行之前看起来像Z = 36ms的延迟。
解决此问题的一种方法是减少睡眠并在需要时跳过迭代。例如,您可以睡眠sleepTime/10
ms,并且在每次迭代时都要检查您是否应该进行帧捕获。
答案 1 :(得分:-1)
好的,所以我很确定Service
是使用Threads的更好选择。根据Android文档:
因为运行服务的进程排名高于进程 与后台活动,一个启动长期运行的活动 相反,操作可能会为该操作启动服务 而不是简单地创建一个工作线程 - 特别是如果操作将 可能比活动更持久。例如,上传的活动 网站上的图片应该启动服务以执行上传 这样即使用户上传也可以在后台继续 离开活动。使用服务可以保证操作 将至少拥有"服务流程"优先,不管是什么 发生在活动中。
有关进程(服务,活动)和主题(及其优先级)here的更多信息。服务可以是后台和前台,更多地了解它们here(这可能会帮助你弄清楚你是否实现了错误,所以你可以解决它。)
至于您的具体问题,请尝试检查sleepTime
值,可能存在一些问题(遗憾的是,我无法测试您的示例,但我会先检查该值),如果仍然不能找出问题所在,然后您应该尝试使用Systrace或Traceview检查您的应用效果,并找出为什么在应用不可见时fps会降低...