在Android开发过程中,常需要更新界面的UI。而更新UI是要主线程来更新的,即UI线程更新。如果在主线线程之外的线程中直接更新页面显示常会报错。抛出异常:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.


只有原始创建这个视图层次(view hierachy)的线程才能修改它的视图(view)        





方法一:Handler实例


      (1) 子类需要继承Handler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据
      以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容

public class MyHandlerActivity extends Activity { 
 
 
 

       Button button; 
 
 
 

       MyHandler myHandler; 
 
 
 
 
  
 
 

       protected void onCreate(Bundle savedInstanceState) { 
 
 
 

           super.onCreate(savedInstanceState); 
 
 
 

           setContentView(R.layout.handlertest); 
 
 
 
 
  
 
 

           button = (Button) findViewById(R.id.button); 
 
 
 

           myHandler = new MyHandler(); 
 
 
 

           // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据 
 
 
 

           // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象 
 
 
 

           // (2): 让一个动作,在不同的线程中执行. 
 
 
 
 
  
 
 

           // 它安排消息,用以下方法 
 
 
 

           // post(Runnable) 
 
 
 

           // postAtTime(Runnable,long) 
 
 
 

           // postDelayed(Runnable,long) 
 
 
 

           // sendEmptyMessage(int) 
 
 
 

           // sendMessage(Message); 
 
 
 

           // sendMessageAtTime(Message,long) 
 
 
 

           // sendMessageDelayed(Message,long) 
 
 
 

          
 
 
 

           // 以上方法以 post开头的允许你处理Runnable对象 
 
 
 

           //sendMessage()允许你处理Message对象(Message里可以包含数据,) 
 
 
 
 
  
 
 

           MyThread m = new MyThread(); 
 
 
 

           new Thread(m).start(); 
 
 
 

       } 
 
 
 
 
  
 
 

       /** 
 
 
 

       * 接受消息,处理消息 ,此Handler会与当前主线程一块运行 
 
 
 

       * */ 
 
 
 
 
  
 
 

       class MyHandler extends Handler { 
 
 
 

           public MyHandler() { 
 
 
 

           } 
 
 
 
 
  
 
 

           public MyHandler(Looper L) { 
 
 
 

               super(L); 
 
 
 

           } 
 
 
 
 
  
 
 

           // 子类必须重写此方法,接受数据 
 
 
 

           @Override 
 
 
 

           public void handleMessage(Message msg) { 
 
 
 

               // TODO Auto-generated method stub 
 
 
 

               Log.d("MyHandler", "handleMessage......"); 
 
 
 

               super.handleMessage(msg); 
 
 
 

               // 此处可以更新UI 
 
 
 

               Bundle b = msg.getData(); 
 
 
 

               String color = b.getString("color"); 
 
 
 

               MyHandlerActivity.this.button.append(color); 
 
 
 
 
  
 
 

           } 
 
 
 

       } 
 
 
 
 
  
 
 

       class MyThread implements Runnable { 
 
 
 

           public void run() { 
 
 
 
 
  
 
 

               try { 
 
 
 

                   Thread.sleep(10000); 
 
 
 

               } catch (InterruptedException e) { 
 
 
 

                   // TODO Auto-generated catch block 
 
 
 

                   e.printStackTrace(); 
 
 
 

               } 
 
 
 
 
  
 
 

               Log.d("thread.......", "mThread........"); 
 
 
 

               Message msg = new Message(); 
 
 
 

               Bundle b = new Bundle();// 存放数据 
 
 
 

               b.putString("color", "我的"); 
 
 
 

               msg.setData(b); 
 
 
 
 
  
 
 

               MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI 
 
 
 
 
  
 
 

           } 
 
 
 

       }




方法二:利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable)。 这样Runnable对像就能在ui程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程






Activity.runOnUiThread(new Runnable()    
 
  
        {    
 
  
            public void run()    
 
  
            {    
 
  
                Toast.makeText(getApplicationContext(), , "Update My UI",    
 
  
                        Toast.LENGTH_LONG).show();    
 
  
            }    
 
  

 
  
        });