Android多线程:Looper和Handler详解

来源:互联网 发布:域名申请后不用 编辑:程序博客网 时间:2024/06/04 20:24

一、认识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-sdkandroid:minSdkVersion="8"android:targetSdkVersion="17" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid: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());}}}

原创粉丝点击