2014-09-23 66 views
-1

剛接觸Android並試圖重複調用invalidate函數。所以我選擇線程來做到這一點。我的線程運行正常,但試圖調用invalidate()時崩潰下面是代碼片段。在一個單獨的線程中調用無效時崩潰

class MyCanvas extends View { 
    private static final String TAG = "MY CANVAS EXAMPLE"; 

    public MyCanvas(Context context){ 
     super(context); 
     Log.e (TAG, " MY CANVAS CONSTRUCTOR GOT CALLED "); 
     // TODO Auto-generated constructor stub 
     Thread newBackground = new Thread (new Runnable(){ 

       @Override 
       public void run() { 
        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
        invalidate(); 
        Log.e (TAG, " MY THREAD GOT CALLED "); 
        // TODO Auto-generated method stub 
       } 
      }); 
     newBackground.start(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     Log.e (TAG, " MY CANVAS GOT CALLED "); 
     // TODO Auto-generated method stub 
     super.onDraw(canvas); 
    }  
} 

和下面是崩潰日誌觀察

09-23 17:41:09.299: E/MY CANVAS EXAMPLE(1839): MY CANVAS CONSTRUCTOR GOT CALLED 
09-23 17:41:09.599: E/MY CANVAS EXAMPLE(1839): MY CANVAS GOT CALLED 
09-23 17:41:10.329: W/dalvikvm(1839): threadid=9: thread exiting with uncaught exception (group=0x40018578) 
09-23 17:41:10.329: E/AndroidRuntime(1839): FATAL EXCEPTION: Thread-10 
09-23 17:41:10.329: E/AndroidRuntime(1839): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
09-23 17:41:10.329: E/AndroidRuntime(1839):  at android.view.ViewRoot.checkThread(ViewRoot.java:3020) 
09-23 17:41:10.329: E/AndroidRuntime(1839):  at android.view.ViewRoot.invalidateChild(ViewRoot.java:647) 
09-23 17:41:10.329: E/AndroidRuntime(1839):  at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:673) 
09-23 17:41:10.329: E/AndroidRuntime(1839):  at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511) 
09-23 17:41:10.329: E/AndroidRuntime(1839):  at android.view.View.invalidate(View.java:5279)  
09-23 17:41:10.329: E/AndroidRuntime(1839):  at com.example.canvas.MainActivity$MyCanvas$1.run(MainActivity.java:83) 
09-23 17:41:10.329: E/AndroidRuntime(1839):  at java.lang.Thread.run(Thread.java:1019) 

回答

0

據我所知,該方法invalidate()不允許被主(UI)線程之外運行。如果你讀你已經得到了異常的細節,那麼你可以看到這一點:

09-23 17:41:10.329: E/AndroidRuntime(1839): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

要解決它,只需使用runOnUiThread()方法運行在主線程上invalidate()This question應該爲您提供更多信息。

編輯:一個更優雅的解決方案是按BlackBelt所述調用postInvalidate()。這樣你就不必創建一個新的Runnable實例。我立場糾正。

0

invalidate();調度視圖層次結構的重新設計,而該視圖層次結構只能由UI線程訪問,而不能從後臺線程訪問。您應該使用postInvalidate()。從文檔

導致指定區域在隨後的事件循環的 循環中發生無效。使用它可以使非UI線程的視圖無效。

1
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

invalidate()只能在主UI線程上調用。

請勿爲此類延遲使用線程。相反,考慮使用HandlerpostDelayed()來發布Runnable以在延遲後在主UI線程上運行。

(還有postInvalidate()如果你想,如果你堅持使用一個單獨的線程從後臺線程發佈一個invalidate()消息。不使用一個單獨的線程是一個更好的選擇。)

相關問題