浅谈Android中的线程与Handler

注意:
 1、在Android中只支持单线程的模式,何为单线程的模式,个人认为是这样的,虽然Android中支持多线程的机制,但是并不是所有的事情都能在子线程中去做得。很重要也是很明确的一点,在Android中的UI是由主线程去更新的,所以说在子线程中是不允许去更新UI的,要到主线程中去更新UI。
2、但是有时候有些事还必须要子线程去做的,比如说在一些网络的操作,循环次数耗时较长的操纵,就不能放在主线程,否则会导致主线程阻塞,主线程阻塞意味着什么,意味着你的主程序就要崩溃了直接报ANR错误(因为一个程序就是一个默认的主线程),这时候你就得去单独开启一个子线程去完成这些耗时的操作。
3、由以上两点特性,大概就可以总结出Android中只支持单线程模式含义,支持单线程模式,就是说一个特定的任务或者操作只能由主线程或者子线程去完成,而不是这个任务既能由主线程又能由子线程去完成。


"Handler的应运而生"

为什么说Handler应运而生呢??,因为正是Android中只支持单线程的模式原因,才导致Handler出现。因为不难分析出,当我有一个子线程去执行一个耗时的任务,但这个任务却有一部分是涉及到更新UI的,那么在子线程中是不能去完成更新UI的操作所以这时候就需要主线程来更新UI,但是问题来了主线程怎么知道它需要更新UI呢??肯定是要有人来告诉它,所以子线程就是通过一个Handler对象来发送消息给主线程,然后Handler对象又到主线程中去处理这些消息,根据消息的标记然后到主线程中去做一些相应的UI更新操作或者其他的操作。所以,Handler就是这样出现了,随即它的作用也明显出来了,就是两点:1、用于发送消息;2、用于接收并处理消息


"幕后默默支持的朋友:Looper的存在"
Handler就是那么简单就把消息从子线程传递到主线程吗??,其实不然,任何完美的事都是需要历经艰险的,人生旅途中需要有很多默默支持的朋友来帮助你,Looper就是扮演着这样的角色。它就是起到了Handler到消息对列的桥梁作用。既然是这种联系,那么他们之间的纽带怎么绑在一起的呢?
很明显,我们现在有三个对象:1 Handler----------->Looper---------->消息队列,
Handler-------->Looper:每一个Handler都会与唯一的线程绑定,而每一个线程又有唯一一个消息队列,作为创建Handler对象时的参数传入,将Looper与Handler绑定
注意:
1、至于Handler是与哪个线程绑定,看这个Handler对象是在哪个线程中创建,与它处于哪个环境下的线程绑定。
2、注意:在主线程中,系统会默认创建一个Looper对象和一个与之绑定的消息队列,而在子线程中则不会,则需要去调用Looper.prepare()获得一个Looper对象,因为Looper是一个静态类不能new出来,而是去获取。
获取到Looper对象还不够还要到HandleMessage后面去启动Looper对象,调用Loop()方法。
获取到主线程的Looper对象方法是:
Looper looper=Looper.getMainLooper();//获取主线程的Looper对象
获取到当前对象:Looper currentLooper=Looper.myLooper();//获取当前的Looper对象
代码:
Looper looper=Looper.getMainLooper();//获取主线程的Looper对象
Looper currentLooper=Looper.myLooper();//获取当前的Looper对象
//Looer.myQueue();获取消息队列,只有主线程系统才会默认给它创建消息队列和Looper对象
private Handler handler=new Handler(looper){//将主线程的传入将Handle与looper绑定
public void handleMessage(Message msg) {//Handle去处理信息,
if (msg.what==0x1111) {
img.setImageResource(imageId[(++current)%imageId.length]);//在主线程中更新UI组件
   String str= (String) msg.obj;
}
};
};
Loop----------->消息队列:
前面也说过了,当创建一个Looper对象就会创建一个与之绑定的消息队列,这个可以通过Android源码中可以看到Looper的构造器中直接去new了一个消息队列对象。


由Handler------>Looper------>消息队列之间的绑定关系,那么就相当于他们之间建立起一个消息、数据通道,那么他们之间通信当然是唯一的,而是可行的。


"Handler的另一份工作":

处理消息,(一个线程只能对应一个Handler对象,一个Handler对象可以对应很多的线程)

Handler扮演着双重角色,既要发送消息,又要处理消息。

Handler会从消息队列中去取出消息,然后根据传来的消息和数据做相应的操作。


"发送消息的类型":
1、空消息,主要会传一个msg.What过去,主要是传一个标志,便于在处理消息时候,判断是哪个子线程传来的消息请求。
2、携带数据的消息,可以传入一个Object类型的对象(msg.obj),也就是可以传任何类型的数据,可以出一个Bundle对象(msg.setData(Bundle data))
以及传一个整型的数据(msg.arg1或msg.arg2);
"发送消息的几种方式":
1、从主线程发送消息给子线程,让子线程去处理消息,做处理。(不常用)
/*
*测试案例一:大家都知道求某个数范围内的所有质数,如果我的范围较小用主线程去做一点问题都没有,但是数据范围一旦变大,就可能会阻塞主线程

所以,现在需要去做这样的操作,从主线程获取我那个数范围,然后在主线程中通过Handler对象去发送消息并携带这个数据到子线程中去,然后到子线程中去处理这个消息并获取到数据,然后在子线程中处理找到这个数范围内的所有质数,这样即使范围再大,只是会阻塞子线程但是并不会是程序崩溃

*/

package com.zhongqihong.threadapp;import java.util.HashSet;import java.util.Set;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.view.View;import android.widget.EditText;import android.widget.Toast;public class OtherActivity extends Activity {private EditText edit;public class MyThread extends Thread{//创建一个子线程类继承Thread作为内部类public Handler handler;@Overridepublic void run() {Looper.prepare();//            handler = new Handler(Looper.myLooper()){               @Override            public void handleMessage(Message msg) {            // TODO Auto-generated method stub               Setset=new HashSet();            if (msg.what==0x1111) {int num=msg.arg1;test:for (int i = 2; i <=num; i++) {for (int j = 2; j < Math.sqrt(i); j++) {if (i!=2&&i%j==0) {   continue test;}}set.add(i);}Toast.makeText(OtherActivity.this, set.toString(), Toast.LENGTH_SHORT).show();}            }               };               Looper.loop();//启动Loop}}private MyThread myThread;public  void myCal(View v) {//先拿到数据,在发送给子线程int num=Integer.parseInt(edit.getText().toString());Message msg=new Message();msg.what=0x1111;msg.arg1=num;myThread.handler.sendMessage(msg);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_other);edit=(EditText) findViewById(R.id.edit);myThread=new MyThread();myThread.start();}}


2、从子线程发送消息给主线程,让主线程去处理消息,做处理(常用,一般用于子线程向主线程发送消息去更新UI)
/*
测试案例二:我要实现一个简单的自动切换图片方法,这就是通过
子线程去通过Handler发送消息给主线程,告诉主线程需要去更新UI

*/

package com.zhongqihong.threadapp;import javax.crypto.spec.IvParameterSpec;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Handler.Callback;import android.os.Looper;import android.os.Message;import android.widget.ImageView;public class MainActivity extends Activity {private ImageView img;/* */Looper looper=Looper.getMainLooper();//获取主线程的Looper对象 Looper currentLooper=Looper.myLooper();//获取当前的Looper对象 //Looer.myQueue();获取消息队列,只有主线程系统才会默认给它创建消息队列和Looper对象private Handler handler=new Handler(looper){//将主线程的传入将Handle与looper绑定public void handleMessage(Message msg) {//Handle去处理信息,if (msg.what==0x1111) {img.setImageResource(imageId[(++current)%imageId.length]);//在主线程中更新UI组件    String str= (String) msg.obj;}};};private int imageId[]={R.drawable.love10,R.drawable.love11,R.drawable.love12,R.drawable.love13,R.drawable.love14};private int current=0;//保存当前显示的图片@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);img=(ImageView) findViewById(R.id.iv);//换图片//启动子线程new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {//会阻塞主线程try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//利用消息机制更新UI//利用发送空消息的方法,发送一个标识,用于区别是哪个子线程请求主线程去更新UI组件//handler.sendEmptyMessage(0x1111);/*携带数据的消息*/Message msg=new Message();//或者Message msg=handle.obtainMessage();msg.what=0x1111;msg.obj="更新消息";handler.sendMessage(msg);}}}).start();}}
个人理解消息机制传递示意图:

浅谈Android中的线程的通信及Handle机制_第1张图片

更多相关文章

  1. Android消息处理机制2——Message
  2. Android完全退出程序、线程
  3. Android 如何获取keyboard和TP消息 分享

随机推荐

  1. VS2013开发Android(安卓)App 环境搭建
  2. android POST请求(https)遇到的问题
  3. android 中文 API- Scroller
  4. Android入门第五篇之TableLayout (二)//
  5. android onMeasure 实现
  6. 面试记录
  7. Android中关联源码的方法
  8. Android应用开发提高系列——Android动态
  9. [Flutter] Flutter之Android开发者教程(
  10. Android(安卓)SimpleAdapter ViewBinder