1. 程式人生 > >Android之多執行緒

Android之多執行緒

這是一個每過三秒 定時彈出一個Toast的小demo Android的執行緒分兩類 一個是不帶訊息的普通執行緒 另一個則是帶訊息的訊息執行緒

先來逐步分析 首先分析訊息處理器Handler 用一個匿名內部類 重寫handleMessage方法 傳入msg 按套路 就是在方法中使用switch 來判斷收到的不同的msg 來處理不同的業務邏輯 然後通過bundle 來接受資料 並且出一Toast

hd=new Handler() { @Override public void handleMessage(Message msg) { //呼叫父類處理 super.handleMessage(msg); //根據訊息what編號的不同,執行不同的業務邏輯 switch(msg.what) { //將訊息中的內容提取出來顯示在Toast中 case Constant.DISPLAY_TOAST: //獲取訊息中的資料 Bundle b=msg.getData(); //獲取內容字串 String msgStr=b.getString(“msg”); //顯示Toast Toast.makeText ( context, msgStr, Toast.LENGTH_SHORT ).show(); break; } } };

下面則是在傳送bundle data->bundle->msg->handle 在這裡插入圖片描述 邏輯則是: 通過bundle傳送訊息到有訊息的執行緒 通過handle來接受並且處理 不過這個有訊息的執行緒很特殊 (訊息執行緒的佇列FIFO模型)為了不影響主執行緒(因為主執行緒主要是負責UI 人機互動介面的) 所以另外建立了一個執行緒 在這個執行緒中合理使用handle 明白了bundle的作用 四份類似與intent 不過intent是隻能在Activity之間互相的傳送而bundle則更加方便。 同時訊息處理的執行緒中 必須要有準備工作Looper.prepare(); 同時執行緒的最後 要進行執行緒的迴圈Looper.loop(); 訊息執行緒千萬不能出現子主執行緒中否則會出出現的執行緒不死的現象 並且 沒有用該機制的後果

錯誤程式碼如下

new Thread()
	    {
	    	@Override
	    	public void run()
	    	{
				this.setName("Thread Dispatch");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
	    	//	迴圈10次,顯示10個Toast
	    		for(int i=1;i<=10;i++)
	    		{
	    			final int k=i;
	    			new Thread()
	    			{
	    				public void run()
	    				{
	    					this.setName("Toast Thread "+k);
	    					Looper.prepare();
			    			//顯示Toast
			        		Toast.makeText
			               	(
			               	   LooperThreadExampleActivity.this,
			               	   "Toast 訊息"+k,
			               	   Toast.LENGTH_SHORT
			               	).show();
			        		Looper.loop();
	    				}
	    			}.start();
	    			//休息3000ms再發下一條訊息
	    			try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
	    		}
	    	}
	    }.start();

在AS的執行緒監控下 執行緒不死 在這裡插入圖片描述

new Thread()
	    {
	    	@Override
	    	public void run()
	    	{
				this.setName("Thread Dispatch");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
	    	//	迴圈10次,顯示10個Toast
	    		for(int i=1;i<=10;i++)
	    		{
	    			final int k=i;
	    			new Thread()
	    			{
	    				public void run()
	    				{
	    					this.setName("Toast Thread "+k);
	    					Looper.prepare();
			    			//顯示Toast
			        		Toast.makeText
			               	(
			               	   LooperThreadExampleActivity.this,
			               	   "Toast 訊息"+k,
			               	   Toast.LENGTH_SHORT
			               	).show();
			        		Looper.loop();
	    				}
	    			}.start();
	    			//休息3000ms再發下一條訊息
	    			try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
	    		}
	    	}
	    }.start();

==================================================================== 原始碼如下

執行緒的程式碼

public class LooperThread extends Thread
{
	//訊息處理器
	Handler hd;
	//上下文
	public Context context;

	public LooperThread(Context context)
	{
		this.context=context;
	}
	
	@Override
	public void run()
	{
		this.setName("Toast Thread 執行緒");
		//進行prepare,建立訊息佇列
		Looper.prepare();

		//建立訊息處理器物件
		hd=new Handler()
		{
			@Override
			public void handleMessage(Message msg)
			{
				//呼叫父類處理
				super.handleMessage(msg);
				//根據訊息what編號的不同,執行不同的業務邏輯
				switch(msg.what)
				{
					//將訊息中的內容提取出來顯示在Toast中
					case Constant.DISPLAY_TOAST:
						//獲取訊息中的資料
						Bundle b=msg.getData();
						//獲取內容字串
						String msgStr=b.getString("msg");
						//顯示Toast
						Toast.makeText
								(
										context,
										msgStr,
										Toast.LENGTH_SHORT
								).show();
						break;
				}
			}
		};
		//建立訊息迴圈
		Looper.loop();
	}
}

============================================================================

Activity的程式碼

public class LooperThreadExampleActivity extends Activity
{
	//有訊息迴圈的執行緒
	LooperThread lt;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		//建立自定義的有訊息迴圈的執行緒的物件
		lt=new LooperThread(this);
		//啟動執行緒
		lt.start();

		//開啟一個普通的執行緒,定時向訊息迴圈執行緒傳送訊息
		new Thread()
		{
			@Override
			public void run()
			{
				//迴圈10次,傳送10條訊息,顯示10個Toast
				for(int i=1;i<=10;i++)
				{
					//建立內容字串
					String msgStr="計數器值:"+i;
					//建立訊息資料Bundle
					Bundle b=new Bundle();
					//將內容字串放進資料Bundle中
					b.putString("msg", msgStr);
					//建立訊息物件
					Message msg=new Message();
					//設定資料Bundle到訊息中
					msg.setData(b);
					//設定訊息的what值
					msg.what=Constant.DISPLAY_TOAST;
					//傳送訊息
					lt.hd.sendMessage(msg);
					//休息3000ms再發下一條訊息
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}
}