Android之Handler探索

Handler背景理解: java

 Handler被最多的使用在了更新UI線程中,可是,這個方法具體是什麼樣的呢?我在這篇博文中先領着你們認識一下什麼是handler以及它是怎麼樣使用在程序中,起着什麼樣的做用。android

  示例說明:多線程

    首先先創建兩個按鈕:一個是start按鈕,做用是開啓整個程序。另外一個是終止按鈕end,做用是結束整個的程序。這兩個按鈕的相互對比就會讓你們明白Handlerd的基本的工做原理。app

運行結果截圖:異步

MainActivity.classide

package com.example.testhandler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {
	
	private Button start,end;

	//實例化一個handler對象
	private Handler handler = new Handler();
	//開啓一個新的線程:開啓線程有兩種方式,一種是使用普通的Thread方法,另外一箇中是使用Runnable方法
	Runnable update = new Runnable() {
		
		@Override
		public void run() {
			System.out.println("update");
			handler.postDelayed(update, 3000);
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		start = (Button)this.findViewById(R.id.btn_start);
		end = (Button)this.findViewById(R.id.btn_end);
		
		start.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//加入到隊列中去執行
				handler.post(update);
			}
		});
		
		end.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//將消息移除隊列中去
				handler.removeCallbacks(update);
			}
		});
		
	}

}

  當點擊Start按鈕時的效果圖以下:oop

當點擊end按鈕時的效果圖以下:佈局

注意:post

  Handler中的post方法並無開啓一個新的線程,他的操做是在主線程中執行的。下面我們就來驗證一下這個觀點。測試

  首先先貼一下運行截圖:

  

  等過10s以後的運行結果是:

  

這裏只是測試一下handler的post()方法是不是在主線程中進行的。因此沒有佈局。

設計思路:

在主線程中輸出主線程當前的ID和Name,而後使用Runnable方式新建一個線程,在這個新線程中讓程序睡眠10s,將這個線程使用Handler的post()方法發送到主線程中,看是不是執行異步加載。也就是驗證handler是不是異步加載方式。結論:Handler不是異步加載方式。

MainActivity:

package com.example.handlertest1;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

	private Handler mhandler = new Handler();
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//將多線程發送到消息隊列中
		mhandler.post(r);
		//不會馬上加載界面,這說明了handler並非開闢了一個新的線程而是在主線程中進行的。
		setContentView(R.layout.activity_main);
		System.out.println("Activity-->"+Thread.currentThread().getId());
		System.out.println("Activity-->"+Thread.currentThread().getName());
	}

	Runnable r = new Runnable() {
		public void run() {
			System.out.println("Handler--->"+Thread.currentThread().getId());
			System.out.println("handler--->"+Thread.currentThread().getName());
			try {
				Thread.sleep(10000);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};
	
}

LogCat文件的輸出:

 

在這裏經過ID號很明顯的看出這不是執行的是多線程加載

在上面的主線程中從新新建一個線程則實現了多線程的加載:

將上面的onCreate()中的代碼替換爲:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //將多線程發送到消息隊列中
//        mhandler.post(r);
        //不會馬上加載界面,這說明了handler並非開闢了一個新的線程而是在主線程中進行的。
        setContentView(R.layout.activity_main);
        //這是另外開啓了一個新的線程,會發現這裏輸出的速率會比上次的快不少
        Thread t = new Thread(r);
        t.start();
        System.out.println("Activity-->"+Thread.currentThread().getId());
        System.out.println("Activity-->"+Thread.currentThread().getName());
    }

效果截圖以下:

LogCat文件中的輸出結果截圖爲:

 

在這裏經過ID號很明顯的看出了這是執行了多線程加載。

  Handler要想開闢一個新的線程須要使用HanderThread()方法。下面就是HandlerThread()的用法:

設計思路:

  經過使用handler方法傳輸數據,而後使用HandlerThread,實現了使用Looper來處理消息隊列的功能。輸出當前的Activity的ID和Name,以及Handler的ID和Name以及傳輸的數據

代碼以下:

 1 package com.example.handlertest1;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 import android.os.HandlerThread;
 7 import android.os.Looper;
 8 import android.os.Message;
 9 
10 public class HandlerTest2 extends Activity{
11 
12     @Override
13     protected void onCreate(Bundle savedInstanceState) {
14         super.onCreate(savedInstanceState);
15         setContentView(R.layout.activity_main);
16         
17         //打印當前線程的ID和當前線程的名字
18         System.out.println("Activity-->"+Thread.currentThread().getId());
19         System.out.println("Activity-->"+Thread.currentThread().getName());
20         
21         //HandlerThread是以鍵值對的形式進行存儲的,這裏的handler_thread就是該handler的鍵名
22         //生成一個HandlerThread對象,實現了使用Looper來處理消息隊列的功能。這是有android來提供的並非java中的Thread提供
23         HandlerThread handlerthread = new HandlerThread("handler_thread");
24         handlerthread.start();
25         MyHandler myhandler = new MyHandler(handlerthread.getLooper());
26         Message msg = myhandler.obtainMessage();
27         //傳送多的數據的時候使用的setData()方法,使用Bundle()將數據包裝
28         Bundle b = new Bundle();
29         b.putInt("age", 20);
30         b.putString("name", "張三");
31         msg.setData(b);
32         //將消息發送給目標,目標就是生成該msg對象的handler
33         msg.sendToTarget();
34         
35     }
36     
37     class MyHandler extends Handler{
38         
39         public MyHandler(){
40             
41         }
42         public MyHandler(Looper looper){
43             super(looper);
44         }
45         
46         @Override
47         public void handleMessage(Message msg) {
48             Bundle b = msg.getData();
49             int age = b.getInt("age");
50             String name = b.getString("name");
51             System.out.println("age is"+age+",name"+name);
52             System.out.println("Handler--->"+Thread.currentThread().getId());
53             System.out.println("Handler--->"+Thread.currentThread().getName());
54             System.out.println("handlermessage");
55         }
56         
57     }
58     
59 }

好了,就這麼多了,具體的關於Handler、Looper、Message三者的關係,參考http://blog.csdn.net/lmj623565791/article/details/38377229我的感受不錯

相關文章
相關標籤/搜索