Android Handler 的使用

  Android UI 操作是线程不安全的。我们只能在UI线程或者说主线程中修改UI。试想多个Thread操作同一个UI,可能引起不一致。UI 线程的主要工作是:UI界面更新显示,各个控件的交互等等。一些耗时(time-consuming)操作不能放在UI线程中,典型的如:查询数据库,网络请求等等。这些操作留给worker线程来做。如何将worker线程的工作结果显示在UI上呢,

Android 提供的解决方法:提供Handler,用于thread之间的通信。通过Handler发送Message或者Runnable到MessageQueen。这其中有许多概念。这些概念是理解Android Thread 的关键。

 

一、实现 worker Thread修改UI。

  worker Thread 是相对主线程Main Thread(UI thread)来说的。

       以简单的实例说明:点击按钮屏幕Toast提示,更新button 文字。

  1.通过handler 向 MessageQueen中发送Message。在Handler 的回调函数 handlerMessage() 中完成UI的更新。

   

public class MainActivity extends Activity {

	private Handler mHandler;
	private Button mButton ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton = (Button)findViewById(R.id.btn);
		mHandler = new Handler(){
			@Override
			public void handleMessage(Message msg){
				updateUI();
			};
		};
		
        mButton.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				new Thread(new Runnable(){

					@Override
					public void run() {
						// TODO Auto-generated method stub
						TimeConsumeTask();
						mHandler.sendEmptyMessage(0);
					}
					
				}).start();
			}
        	
        });
    }
    
  // 更新UI操作 public void updateUI(){ Toast.makeText(getApplicationContext(), "更新UI", Toast.LENGTH_LONG).show(); mButton.setText("UI update"); }
  // 模拟耗时操作 public void TimeConsumeTask(){ try { Thread.sleep(1500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

  mHandler 为Activity 的成员变量,handleMessage函数中的更新UI操作是在UI线程中完成的。

   显示:

  

  2.通过handler 向 MessageQueen中Post Runnable 对象,Runnable对象中执行的是UI更新操作。

    将上面上的代码稍作改动:

 

public class MainActivity extends Activity {

	private Handler mHandler;
	private Button mButton ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton = (Button)findViewById(R.id.btn);
//		mHandler = new Handler(){
//			@Override
//			public void handleMessage(Message msg){
//				updateUI();
//			};
//		};
        mHandler = new Handler();
		
        mButton.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				new Thread(new Runnable(){

					@Override
					public void run() {
						// TODO Auto-generated method stub
						TimeConsumeTask();
						//mHandler.sendEmptyMessage(0);
						mHandler.post(new Runnable(){

							@Override
							public void run() {
								// TODO Auto-generated method stub
								updateUI();
							}
							
						});
					}
					
				}).start();
			}
        	
        });
    }
    
    public void updateUI(){
    	Toast.makeText(getApplicationContext(), "更新UI", Toast.LENGTH_LONG).show();
    	mButton.setText("UI update");
    }
    
    public void TimeConsumeTask(){
    	try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
}

  运行结果是一样的。

  mHandler post Runnable对象到了UI thread 的MessageQueen中,UI thread的 Looper 负责处理MessageQueen中的message,Runnable中的更新UI代码最终是在UI thread中执行的。

posted @ 2016-09-19 09:32  googlg  阅读(458)  评论(0编辑  收藏  举报