2010-08-12 21 views
25

在我的Android應用程序中,當我按下UI上的按鈕(圖像)時,整個應用程序凍結,幾秒鐘後出現可怕的強制關閉對話框。Android - 重點調度超時

這裏是獲取打印日誌中:


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} [email protected] 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} [email protected] 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' 

這是按鈕的代碼(圖片):


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)); 
        } 
      });  

如果我評論如下走出按下按鈕(圖像)不會導致飛機墜毀:


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

上面的代碼調用向下通過應用程序的幾個層次,併爲本地層(NDK),可以通過幾個物體的呼叫導致力量關閉?這看起來不太可能,因爲其他幾個按鈕都沒有問題。

原生圖層如何?我用NDK構建的一些代碼是否會導致這個問題?

關於問題的原因可能是什麼的其他想法?

回答

35

您的onClick實施必須儘可能快。通常,昂貴的操作應該被卸載到後臺線程。

在的onClick,嘗試:

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

,而不是僅僅

your_stuff() 
4

當你阻塞主線程(又稱爲UI線程),你可以遇到這個錯誤幾秒鐘。通常,昂貴的操作應該被卸載到後臺線程。在這些情況下,AsyncTask非常有幫助。

在你的情況,你可以做到以下幾點:

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

如果你正在做一個資源密集型任務,那麼它可能會發生。在恢復活動時。 1.嘗試停止onPause的所有密集工作,然後在onResume上重新啓動它。 2.如果您在其上顯示活動繪製疊加圖上的地圖,則停止在睡眠狀態下刷新疊加層。然後在onResume上重新啓動它。

0

在單獨的線程中執行您的長操作或使用AsyncTask來擺脫ANR。

an ANR(Activity Not Responding)發生在某些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

你應該將你的XML解析代碼到另一個線程,然後使用一個回調來告訴你已經完成了UI線程和做的結果的東西。

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

檢測符合ANR的發生是容易的,如果它是一個永久的塊(死鎖獲取比如一些鎖),但更難如果它只是一個暫時的延遲。首先,檢查你的代碼並尋找可用的點和長時間運行的操作。示例可能包括在事件線程中使用套接字,鎖,線程休眠和其他阻塞操作。你應該確保這些都發生在不同的線程中。如果沒有問題,請使用DDMS並啓用線程視圖。這顯示了您的應用程序中的所有線程與您所擁有的跟蹤相似。重現ANR,並同時刷新主線程。這應該正是告訴你在什麼的ANR

時間延長。如果logcat的不輸出任何有用的,嘗試從/data/anr/traces.txt

adb pull /data/anr/traces.txt . 

爲拉traces.txt它可能會提供有關ANR異常發生位置的更多信息

this link也可能有助於創建AsyncTask和線程