Android应用程序在将代码移动到runnable后冻结,没有ANR
我正在实现一个自定义相机,并使用onPreviewFrame()进行实时特效。主要效果(fx1)是可运行的,看起来还可以,在需要时删除帧。Android应用程序在将代码移动到runnable后冻结,没有ANR,android,freeze,runnable,Android,Freeze,Runnable,我正在实现一个自定义相机,并使用onPreviewFrame()进行实时特效。主要效果(fx1)是可运行的,看起来还可以,在需要时删除帧。 当fx1关闭时,第二个更简单的fx(fx2)将运行。 当fx2在主线程上运行时是正常的(它在2毫秒内运行),但有时我看到一个ANR,所以我决定将其移动到第二个可运行,但现在导致应用程序冻结 class FX2Runnable implements Runnable { private byte[] data; FX2Runnable(byte
当fx1关闭时,第二个更简单的fx(fx2)将运行。
当fx2在主线程上运行时是正常的(它在2毫秒内运行),但有时我看到一个ANR,所以我决定将其移动到第二个可运行,但现在导致应用程序冻结
class FX2Runnable implements Runnable {
private byte[] data;
FX2Runnable(byte[] _data) {
data = _data;
}
public void run() {
hview.FX2(data);
hview.post(new Runnable() {
public void run() {
hview.postInvalidate();
//.invalidate(); caused ANR!!
}
});
FLAG_FX2_PROCESSING = false;
}
}
我这样称呼它
private PreviewCallback previewCallback=new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera cam) {
if(FX==1) {
// FX1
if(FLAG_FX1_PROCESSING) {
//skip
} else {
FLAG_FX1_PROCESSING = true;
FX1Thread = new Thread(new FX1Runnable());
FX1Thread.start();
}
} else {
// FX2
if(FLAG_FX2_PROCESSING) {
//skip
} else {
FLAG_FX2_PROCESSING = true;
FX2Thread = new Thread(new FX2Runnable(data));
FX2Thread.start();
}
/* this was the old code and was working fine
but i needed to solve some spare ANR
//hview.FX2(data);
//hview.invalidate();
*/
}
}
}
我做错了什么
顺便说一下,我似乎无法在模拟器上冻结应用程序,只能在我的设备上冻结
编辑
尝试使用runOnUiThread(Runnable)而不是hview.post(Runnable),它似乎可以工作,但我不得不等几分钟才能再次看到冻结应用程序!后来发生了,但又发生了
这是一只logcat
08-26 17:32:13.398: I/ActivityManager(250): Displayed it.jcsoft.abbracadabbra/.EnhancedCameraPreviewActivity: +3s576ms
08-26 17:32:13.414: W/IInputConnectionWrapper(459): showStatusIcon on inactive InputConnection
08-26 17:32:13.441: I/GPS(9149): new network location: Location[mProvider=network,mTime=1377531132668,mLatitude=44.1459721,mLongitude=12.4545174,mHasAltitude=false,mAltitude=0.0,mHasSpeed=false,mSpeed=0.0,mHasBearing=false,mBearing=0.0,mHasAccuracy=true,mAccuracy=43.887,mExtras=Bundle[mParcelledData.dataSize=212]]
08-26 17:32:15.441: D/dalvikvm(250): WAIT_FOR_CONCURRENT_GC blocked 0ms
08-26 17:32:15.867: D/dalvikvm(250): GC_EXPLICIT freed 1300K, 23% free 16030K/20615K, paused 3ms+41ms, total 428ms
08-26 17:32:37.707: D/dalvikvm(250): GC_CONCURRENT freed 1878K, 22% free 16105K/20615K, paused 4ms+110ms, total 888ms
08-26 17:32:37.855: D/dalvikvm(9149): null clazz in OP_INSTANCE_OF, single-stepping
08-26 17:32:49.375: D/dalvikvm(834): GC_CONCURRENT freed 512K, 9% free 9179K/9991K, paused 336ms+218ms, total 4454ms
08-26 17:32:49.375: D/dalvikvm(834): WAIT_FOR_CONCURRENT_GC blocked 1740ms
08-26 17:32:58.605: D/dalvikvm(250): GC_CONCURRENT freed 1934K, 22% free 16098K/20615K, paused 5ms+32ms, total 284ms
08-26 17:33:00.070: D/SizeAdaptiveLayout(335): com.android.internal.widget.SizeAdaptiveLayout@422dcb90child view android.widget.FrameLayout@422edb18 measured out of bounds at 95px clamped to 96px
08-26 17:33:00.093: D/SizeAdaptiveLayout(335): com.android.internal.widget.SizeAdaptiveLayout@4231b860child view android.widget.FrameLayout@4231d180 measured out of bounds at 95px clamped to 96px
08-26 17:33:10.257: D/dalvikvm(9149): GC_CONCURRENT freed 455K, 4% free 14709K/15303K, paused 3ms+4ms, total 78ms
08-26 17:33:20.082: D/dalvikvm(250): GC_CONCURRENT freed 1933K, 22% free 16091K/20615K, paused 5ms+30ms, total 282ms
08-26 17:33:23.379: I/InputDispatcher(250): Application is not responding: Window{425f23b0 it.jcsoft.abbracadabbra/it.jcsoft.abbracadabbra.EnhancedCameraPreviewActivity paused=false}. It has been 5002.6ms since event, 5002.5ms since wait started. Reason: Waiting because the touched window has not finished processing the input events that were previously delivered to it.
08-26 17:33:23.379: I/WindowManager(250): Input event dispatching timed out sending to it.jcsoft.abbracadabbra/it.jcsoft.abbracadabbra.EnhancedCameraPreviewActivity
08-26 17:33:28.437: I/InputDispatcher(250): Dropped event because it is stale.
请帮忙 不要使用
hview.post…
,尝试使用rununuithread(new Runnable()…
在Android文档中有以下文字
在UI线程上运行指定的操作。如果当前线程是UI线程,则立即执行该操作。如果当前线程不是UI线程,则将该操作发布到UI线程的事件队列
因此,每当您想从线程更新视图时,都需要使用runOnUiThread
所有视图都在UIThread上呈现。如果不这样做,它将崩溃,因为后台线程与UIThread不同。对于此类操作,您确实应该使用处理程序 让runnable在完成其操作后发布消息,然后执行hview.postInvalidate()方法调用 有很多指导如何做 一些链接包括:
不要使用
hview.post…
,尝试使用rununuithread(new Runnable()…
我使用的是View.post,它“导致Runnable被添加到消息队列中。Runnable将在用户界面线程上运行”.有什么区别吗?@j.c UI意味着用户界面。你正在查看的屏幕是在UI线程上运行的。Camera也在使用canvas为我们服务。因此,它也是一种UI视图。你不能在后台修改它。UI线程可以执行更新小部件、视图、事件处理等任务。@j.c、Upvote和acceptance将是一种极大的乐趣。..T他将使未来的谷歌帮助找到有效的答案。:)好的,我想View.post()也会这样,在UI线程上发布“结果”从我的背景线程来看,实际上我仍然不明白为什么它不起作用,无论如何谢谢你的帮助!@j.c你不应该投票,因为答案不正确。谢谢你!当然我不记得我是如何解决这个问题的,无论如何我认为处理程序是正确的方法。可能我做了类似的事情:thread fx2=new thread(new Runnable)(){public void run(){hview.fx2(数据);updateUIHandler.post(新Runnable(){public void run(){hview.invalidate();}}}});}}});fx2.start();这是对的吗?从注释代码来看,它看起来相当不错。除了你不必在处理程序上做.post。然后,如何使用处理程序!?我会使用updateUIHandler在UIthread中更新hview,如何做?处理程序是一种将消息从另一个线程发布到UI线程的方法。因此,如果你发送handler.sendMessage(“key”)在非ui线程中,您必须使用接收消息的处理程序创建回调,然后在ui线程中运行代码。您不必再将其发布到视图中(除非尚未绘制视图)。让我解释一下…摄影机引擎每秒调用onPreviewFrame()30次,我需要更新视图(hview)在fx2(数据)结束显示fx2结果后,这就是我使用hview.post的原因。唯一必须在UIthread上运行的是hview.invalidate(),以便调用onDraw()并更新hview。我为什么要使用消息?我的推理是否有问题?