Android多线程:Looper和Handler详解

一、认识Looper和Handler对象

  当主线程诞生时,就会去执行一个消息循环(Message Loop),以便持续监视它的消息队列(Message Queue简称MQ)。当UI事件发生了,通常会立即丢一个Message给MQ,此时主线程就立即从MQ里边取出该消息并处理。比如,用户在UI界面上按下一个Button按钮时,UI事件发生了,就会丢一些消息到MQ里,其中包括onClick消息,于是,主线程会及时从MQ取出onClick消息,然后调用Activity的onClick()函数去处理。处理完毕后,主线程又返回去继续执行消息循环,继续监视MQ,并一直循环下去,直到主线程的生命周期结束。通常是进程被删除时,主线程才会被删除。

  Android里有一个Looper类,其对象里含有一个消息循环。也就是说,一个主线程有它自己专属的Looper对象,此线程诞生时,就会执行此对象里的消息循环。此外,一个主线程还会有其专属的MQ数据结构。

  由于主线程会持续监视MQ的动态,所以在程序的任何函数,只要将消息丢入主线程的MQ里,就能与主线程通信了。

  在Android,定义了一个Handler类,在程序的任何函数里,可以诞生Handler对象来将Message对象丢到MQ里,而与主线程通信。

  在Android默认情况下,主线程诞生时,就会拥有自己的Looper对象和MQ数据结构。然而,主线程诞生子线程时,默认情况下,子线程并不具有自己的Looper和MQ。由于没有Looper对象,就没有消息循环(Message Loop),一旦工作完毕了,子线程就结束了,无法继续监视MQ,也就不需要MQ了。既然没有Looper对象也没有MQ,也就不能接受外部的Message对象了。则别的线程就无法透过MQ来传递消息给它了。

  也就是说,如果别的线程(如主线程)需要跟子线程相互通信时,就必须替子线程诞生一个Looper对象和一个MQ数据结构,并通过Handler来发送和处理消息。

下面通过实例进一步掌握Handler和Looper的用法:

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.misoo.pkxx"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".ac08"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

二、主线程丢消息给自己

public class ac01 extends Activity implements OnClickListener {
	private Button btn0, btn1;
	private Handler handler;
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);
		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("发送消息");
		btn0.setOnClickListener(this);
		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("退出");
		btn1.setOnClickListener(this);
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(135,
				50);
		params.topMargin = 10;
		layout.addView(btn0, params);
		layout.addView(btn1, params);
		setContentView(layout);
		handler = new Handler() {
			public void handleMessage(Message msg) {
				setTitle((String) msg.obj);
			}
		};
	}
	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			handler.removeMessages(0);
			Message message = handler.obtainMessage(1, 1, 1, "this is my message");
			handler.sendMessage(message);
			break;
		case 102:
			finish();
			break;
		}
	}
}

三、子线程丢消息给主线程

public class ac02 extends Activity implements OnClickListener {
	private Button btn0, btn1;
	private Handler handler;
	private Timer timer = new Timer();
	private Integer k = 0;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);

		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("发送消息");
		btn0.setOnClickListener(this);

		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("退出");
		btn1.setOnClickListener(this);

		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(135,
				50);
		params.topMargin = 10;
		layout.addView(btn0, params);
		layout.addView(btn1, params);

		setContentView(layout);

		handler = new Handler() {
			public void handleMessage(Message msg) {
				setTitle((String) msg.obj);
			}

		};
	}

	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			TimerTask timerTask = new TimerTask() {
				public void run() {
					handler.removeMessages(0);
					Message message = handler.obtainMessage(
							1,
							1,
							1,
							Thread.currentThread().getName() + ":"
									+ String.valueOf(k++));
					handler.sendMessage(message);
				}
			};
		    timer.schedule(timerTask, 500, 1500);
			break;
		case 102:
			finish();
			break;
		}
	}
}

四、替子线程产生Looper和MQ

public class ac03 extends Activity implements OnClickListener {
	private Thread thread = null;
	private Button btn0, btn1, btn2;
	private Handler handler;
	private String string;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);

		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("运行子线程");
		btn0.setOnClickListener(this);

		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("显示内容");
		btn1.setOnClickListener(this);

		btn2 = new Button(this);
		btn2.setId(103);
		btn2.setText("退出");
		btn2.setOnClickListener(this);

		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(100,
				50);
		params.topMargin = 10;
		layout.addView(btn0, params);
		layout.addView(btn1, params);
		layout.addView(btn2, params);

		setContentView(layout);

		thread = new Thread(new Task());
		
		thread.start();

	}

	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			Message msg = handler.obtainMessage(1, 33, 1, null);
			handler.sendMessage(msg);
			break;
		case 102:
			setTitle(string);
			break;
		case 103:
			handler.getLooper().quit();
			finish();
			break;
		}
	}

	class Task implements Runnable {
		public void run() {
			Looper.prepare();
			handler = new Handler(){
				public void handleMessage(Message msg) {
					string = Thread.currentThread().getName() + ":"
							+ String.valueOf(msg.arg1);
				}
			};
			Looper.loop();
		}
	}
}

五、取得主线程的Looper

public class ac04 extends Activity implements OnClickListener {

	private Thread thread;
	private Button btn0, btn1;
	private Handler handler;
	private String string;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);

		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("启动子线程");
		btn0.setOnClickListener(this);

		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("退出");
		btn1.setOnClickListener(this);

		LayoutParams params = new LayoutParams(135, 50);
		layout.addView(btn0, params);
		layout.addView(btn1, params);

		setContentView(layout);

		thread = new myThread();
		thread.start();

	}

	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			Message msg = handler.obtainMessage(1, 33, 1, null);
			handler.sendMessage(msg);
			break;
		case 102:
			finish();
			break;
		}
	}

	class myThread extends Thread {
		public void run() {
			Looper.prepare();
			handler = new Handler(getMainLooper()) {
				public void handleMessage(Message msg) {
					string = Thread.currentThread().getName() + ", value="
							+ String.valueOf(msg.arg1);
					setTitle(string);
				}

			};
			Looper.loop();
		}
	}
}

六、取得子线程的Looper

public class ac05 extends Activity implements OnClickListener{

	private Thread thread;
	private Button btn0, btn1, btn2;
	private Looper looper;
	private String string;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);
		LayoutParams params = new LayoutParams(135, 60);
		
		btn0 = new Button(this); btn0.setId(101);
		btn0.setText("启动子线程"); btn0.setOnClickListener(this);
		
		btn1 = new Button(this); btn1.setId(102);
		btn1.setText("显示内容"); btn1.setOnClickListener(this);
		
		btn2 = new Button(this); btn2.setId(103);
		btn2.setText("退出"); btn2.setOnClickListener(this);
		
		layout.addView(btn0, params);
		layout.addView(btn1, params);
		layout.addView(btn2, params);
		
		setContentView(layout);
		
		thread = new Thread(new myThread());
		thread.start();
	}

	public void onClick(View v) {
		switch(v.getId()){
		case 101:
			Handler handler = new Handler(looper){
				public void handleMessage(Message msg) {
					string = Thread.currentThread().getName()
							+ ", value=" 
							+ String.valueOf(msg.arg1);
				}
			};
			Message msg = handler.obtainMessage(1, 33, 1, null);
			handler.sendMessage(msg);
			break;
		case 102:
			setTitle(string);
			break;
		case 103:
			finish();
			break;
		}
	}

	class myThread extends Thread{
		public void run() {
			Looper.prepare();
			looper = Looper.myLooper();
			Looper.loop();
		}
	}
}

七、定义Handler子类别

public class ac06 extends Activity implements OnClickListener {
	private Thread thread;
	private Button btn0, btn1, btn2;
	private Looper looper;
	private String string;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);
		LayoutParams params = new LayoutParams(135, 60);

		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("启动子线程");
		btn0.setOnClickListener(this);

		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("显示内容");
		btn1.setOnClickListener(this);

		btn2 = new Button(this);
		btn2.setId(103);
		btn2.setText("退出");
		btn2.setOnClickListener(this);

		layout.addView(btn0, params);
		layout.addView(btn1, params);
		layout.addView(btn2, params);

		setContentView(layout);

		thread = new Thread(new myThread());
		thread.start();
	}

	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			myHandler handler = new myHandler(looper);
			Message msg = handler.obtainMessage(1, 33, 1, null);
			handler.sendMessage(msg);
			break;
		case 102:
			setTitle(string);
			break;
		case 103:
			looper.quit();
			finish();
			break;
		}
	}

	class myThread extends Thread {
		public void run() {
			Looper.prepare();
			looper = Looper.myLooper();
			Looper.loop();
		}
	}
	
	class myHandler extends Handler{
		public myHandler(Looper looper) {
			super(looper);
		}

		public void handleMessage(Message msg) {
			string = Thread.currentThread().getName()
					+ ", value="
					+ String.valueOf(msg.arg1);
		}
	}
}

八、主线程和子线程之间互传信息

public class ac07 extends Activity implements OnClickListener {
	private Thread thread;
	private Button btn0, btn1;
	private int value = 0;
	private Looper looper;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);

		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("启动子线程");
		btn0.setOnClickListener(this);

		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("退出");
		btn1.setOnClickListener(this);

		LayoutParams params = new LayoutParams(135, 50);
		layout.addView(btn0, params);
		layout.addView(btn1, params);

		setContentView(layout);

		thread = new myThread();
		thread.start();
	}

	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			subHandler handler = new subHandler(looper);
			Message message = handler.obtainMessage(1, 33, 1, null);
			handler.sendMessage(message);
			break;
		case 102:
			looper.quit();
			finish();
			break;
		}
	}

	class myThread extends Thread {
		public void run() {
			Looper.prepare();
			looper = Looper.myLooper();
			Looper.loop();
		}
	}

	class mainHandler extends Handler {
		public mainHandler() {
			super(Looper.getMainLooper());
		}

		public void handleMessage(Message msg) {
			setTitle(String.valueOf(msg.arg1));
		}
	}

	class subHandler extends Handler {
		public subHandler(Looper looper) {
			super(looper);
		}

		public void handleMessage(Message msg) {
			value = msg.arg1;
			++value;
			
			Handler handler = new mainHandler();
			Message m = handler.obtainMessage(1, value, 1, null);
			handler.sendMessage(m);
		}
	}
}

九、两个子线程之间互传信息

public class ac08 extends Activity implements OnClickListener {
	private Thread thread1, thread2;
	private Button btn0, btn1;
	private int value = 0;
	private Looper looper1, looper2;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);

		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("启动子线程");
		btn0.setOnClickListener(this);

		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("退出");
		btn1.setOnClickListener(this);

		LayoutParams params = new LayoutParams(135, 50);
		layout.addView(btn0, params);
		layout.addView(btn1, params);

		setContentView(layout);
		
		thread1 = new myThread1();
		thread1.start();
		
		thread2 = new myThread2();
		thread2.start();
	}

	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			t1Handler t1h = new t1Handler();
			Message message = t1h.obtainMessage(1, 33, 1, null);
			t1h.sendMessage(message);
			break;
		case 102:
			looper1.quit();looper2.quit();
			finish();
			break;
		}
	}

	class myThread1 extends Thread {
		public void run() {
			Looper.prepare();
			looper1 = Looper.myLooper();
			Looper.loop();
		}
	}

	class myThread2 extends Thread {
		public void run() {
			Looper.prepare();
			looper2 = Looper.myLooper();
			Looper.loop();
		}
	}

	class mainHandler extends Handler {
		public mainHandler() {
			super(Looper.getMainLooper());
		}

		public void handleMessage(Message msg) {
			setTitle(String.valueOf(msg.arg1));
		}
	}

	class t1Handler extends Handler {
		public t1Handler() {
			super(looper1);
		}

		public void handleMessage(Message msg) {
			t2Handler t2h = new t2Handler();
			Message message = t2h.obtainMessage(1, msg.arg1, 1, null);
			t2h.sendMessage(message);
		}
	}

	class t2Handler extends Handler {
		public t2Handler() {
			super(looper2);
		}

		public void handleMessage(Message msg) {
			value = msg.arg1;
			++value;
			mainHandler mh = new mainHandler();
			Message message = mh.obtainMessage(1, value, 1, null);
			mh.sendMessage(message);
		}
	}
}

十、将Runnable对象丢到MQ

public class ac09 extends Activity implements OnClickListener{
	private Thread thread;
	private Button btn0, btn1;
	private int value = 0;
	private Looper looper;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);

		btn0 = new Button(this);
		btn0.setId(101);
		btn0.setText("启动子线程");
		btn0.setOnClickListener(this);

		btn1 = new Button(this);
		btn1.setId(102);
		btn1.setText("退出");
		btn1.setOnClickListener(this);

		LayoutParams params = new LayoutParams(135, 50);
		layout.addView(btn0, params);
		layout.addView(btn1, params);

		setContentView(layout);

		thread = new myThread();
		thread.start();
	}
	
	public void onClick(View v) {
		switch (v.getId()) {
		case 101:
			subHandler handler = new subHandler(looper);
			Message message = handler.obtainMessage(1, 33, 1, null);
			handler.sendMessage(message);
			break;
		case 102:
			looper.quit();
			finish();
			break;
		}
	}

	class myThread extends Thread {
		public void run() {
			Looper.prepare();
			looper = Looper.myLooper();
			Looper.loop();
		}
	}

	class mainHandler extends Handler {
		public mainHandler(Looper looper) {
			super(looper);
		}

		public void handleMessage(Message msg) {}
	}

	class myRun implements Runnable{
		public void run() {
			setTitle(String.valueOf(value + 1));
		}
	}
	
	class subHandler extends Handler {
		public subHandler(Looper looper) {
			super(looper);
		}

		public void handleMessage(Message msg) {
			value += msg.arg1;

			Handler handler = new mainHandler(Looper.getMainLooper());
			Message m = handler.obtainMessage(1, value, 1, null);
			handler.post(new myRun());
		}
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值