2014-09-23 36 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()消息。不使用一个单独的线程是一个更好的选择。)

相关问题