Android – 重点调度超时

在我的Android应用程序中,我遇到了一个非常奇怪的崩溃,当我按下我的用户界面上的一个button(图像)时,整个应用程序冻结,几秒钟之后,出现可怕的强制closures对话框。

以下是在日志中打印的内容:


WARN/WindowManager(88): Key dispatching timed out sending to package name/Activity WARN/WindowManager(88): Dispatch state: {{KeyEvent{action=1 code=5 repeat=0 meta=0 scancode=231 mFlags=8} to Window{432bafa0 com.android.launcher/com.android.launcher.Launcher paused=false} @ 1281611789339 lw=Window{432bafa0 com.android.launcher/com.android.launcher.Launcher paused=false} lb=android.os.BinderProxy@431ee8e8 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4335fc58 package name/Activity paused=false}}} WARN/WindowManager(88): Current state: {{null to Window{4335fc58 package name/Activity paused=false} @ 1281611821193 lw=Window{4335fc58 package name/Activity paused=false} lb=android.os.BinderProxy@434c9bd0 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4335fc58 package name/Activity paused=false}}} INFO/ActivityManager(88): ANR in process: package name (last in package name) INFO/ActivityManager(88): Annotation: keyDispatchingTimedOut INFO/ActivityManager(88): CPU usage: INFO/ActivityManager(88): Load: 5.18 / 5.1 / 4.75 INFO/ActivityManager(88): CPU usage from 7373ms to 1195ms ago: INFO/ActivityManager(88): package name: 6% = 1% user + 5% kernel / faults: 7 minor INFO/ActivityManager(88): system_server: 5% = 4% user + 1% kernel / faults: 27 minor INFO/ActivityManager(88): tiwlan_wifi_wq: 3% = 0% user + 3% kernel INFO/ActivityManager(88): mediaserver: 0% = 0% user + 0% kernel INFO/ActivityManager(88): logcat: 0% = 0% user + 0% kernel INFO/ActivityManager(88): TOTAL: 12% = 5% user + 6% kernel + 0% softirq INFO/ActivityManager(88): Removing old ANR trace file from /data/anr/traces.txt INFO/Process(88): Sending signal. PID: 1812 SIG: 3 INFO/dalvikvm(1812): threadid=7: reacting to signal 3 INFO/dalvikvm(1812): Wrote stack trace to '/data/anr/traces.txt' 

这是Button(Image)的代码:


 findViewById(R.id.endcallimage).setOnClickListener(new OnClickListener() { public void onClick(View v) { mNotificationManager.cancel(2); Log.d("Handler", "Endcallimage pressed"); if(callConnected) elapsedTimeBeforePause = SystemClock.elapsedRealtime() - stopWatch.getBase(); try { serviceBinder.endCall(lineId); } catch (RemoteException e) { e.printStackTrace(); } dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.FLAG_SOFT_KEYBOARD)); dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK)); } }); 

如果我按下button(图像)注释以下内容不会导致崩溃:


 try { serviceBinder.endCall(lineId); } catch (RemoteException e) { e.printStackTrace(); } 

上面的代码通过应用程序的几个级别调用并进入本地层(NDK),通过几个对象传递的呼叫是否会导致closures? 这似乎不太可能,因为其他几个button也没有问题。

原生图层怎么样? 我用NDK构build的一些代码是否会导致这个问题?

任何其他的想法可能是什么原因的问题?

您的onClick实施必须尽可能快。 昂贵的操作通常应该被卸载到后台线程。

在onClick中,请尝试:

 Thread t = new Thread(){ public void run(){ your_stuff(); } }; t.start(); 

而不是仅仅

 your_stuff() 

当您阻塞主线程(也称为UI线程)几秒钟时,您可能会遇到此错误。 昂贵的操作通常应该被卸载到后台线程。 AsyncTask在这些情况下非常有帮助。

在你的情况下,你可以做到以下几点:

 new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { try { serviceBinder.endCall(lineId); } catch (RemoteException e) { e.printStackTrace(); } } }.execute(); 

如果您正在进行资源密集型任务,那么可能会发生。 在恢复活动。 1.尝试停止onPause的所有密集工作,然后在onResume上重新启动它。 2.如果您在活动制图叠加层上显示地图,则停止在睡眠状态下刷新叠加层。 然后在onResume上重新启动它。

在一个单独的线程中进行长操作,或使用AsyncTask来摆脱ANR。

ANR(Activity Not Responding) long operation takes place in the "main"线程中发生一些long operation takes place in the "main" 。 这是事件循环线程,如果它是繁忙的,Android不能在应用程序中处理任何进一步的GUI事件,从而抛出一个ANR dialog

你的活动花了很长时间来说,Android操作系统“嘿,我还活着”! (这是UI线程所做的)。

http://developer.android.com/guide/practices/design/responsiveness.html

基本上,如果你让UI线程执行一些复杂的任务,那么你的任务就是忙于告诉操作系统它仍然是“活着的”。

http://android-developers.blogspot.co.uk/2009/05/painless-threading.html

您应该将您的XMLparsing代码移动到另一个线程,然后使用callback来告诉UI线程已经完成,并对结果进行处理。

http://developer.android.com/resources/articles/timed-ui-updates.html

如果ANR是一个永久性块(死锁获得一些锁),检测ANR发生在哪里很容易,但是如果这只是一个暂时的延迟,则很难。 首先,检查你的代码,寻找可疑的点和长时间运行的操作。 示例可能包括在事件线程中使用套接字,锁,线程hibernate和其他阻塞操作。 你应该确保这些都发生在不同的线程中。 如果没有什么问题,请使用DDMS并启用线程视图。 这显示了您的应用程序中的所有线程与您所拥有的跟踪相似。 重现ANR,同时刷新主线程。 这应该告诉你在ANR的时候到底发生了什么

如果Logcat不输出任何有用的信息,请尝试从/data/anr/traces.txt中提取traces.txt

 adb pull /data/anr/traces.txt . 

因为它可能会提供有关ANRexception发生位置的更多信息

而这个链接也可能有助于创buildAsyncTask和线程