2017年6月6日 星期二

[轉] Error: Only the original thread that created a view hierarchy can touch its views

如果我們想要在另一個Thread中操控 UI ,在Swing中我們可以直接使用(可能會有些問題,不過還是可以直接用),不過,在Android就不行了。


如果我們直接使用的話,會丟出一個 android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views 錯誤


我們必須透過Message的傳遞來達到目的。


也蠻簡單的,


在要被操作的UI物件中(如View)宣告一個 android.os.Handler 物件,


然後覆寫public void handleMessage(Message msg),在該方法中便可以對UI進行操作。


而在Thread中則負責送出android.os.Message 物件到該 Handler。


這樣說好像不夠清楚,看一下code就懂了


// 做一個可以利用Thread修改的View
public class MyView extends View implements Runnable
{
    public static final int MEG_INVALIDATE = 9527; //自訂一個號碼
    
    private Thread thread;
    
    // Constructor
    public AnimationView(Context context) 
    {
        super(context);
    }


  public AnimationView(Context context, AttributeSet attrs) 
  {
        super(context, attrs);
  }
      
  Handler handler = new Handler() 
  {
        public void handleMessage(Message msg) 
  {
    switch (msg.what) 
{
// 當收到的Message的代號為我們剛剛訂的代號就做下面的動作。
case MEG_INVALIDATE:
// 重繪UI
invalidate();
break;
            }
    super.handleMessage(msg);
        }
    };
    
    // 建立 Thread,並開始
    public void init()
  {
  thread = new Thread(this);
thread.start();
  }
    // invalidate() 會呼叫到 onDraw
    public void onDraw(Canvas canvas) 
  {
  
  }

  // Runnable 介面
    public void run() 
  {
  Message m = new Message();
// 定義 Message的代號,handler才知道這個號碼是不是自己該處理的。
m.what = MEG_INVALIDATE;
handler.sendMessage(m);
  }

}

沒有留言:

張貼留言