浅谈Handler

来源:互联网 发布:文案工作 知乎 编辑:程序博客网 时间:2024/04/29 10:04

 浅谈Handler

一、前言

              年即将过完了,眼看有到上班时间了,今年打算换个新工作,所以要准备一下面试,今天简单看了一下handler,已被面试可能会问,再次也在博客上进行一下简单的记录,言归正传,浅谈Handler........,本博客只做知识简单梳理,大神勿看。
         Handler:作用,在android中,android为我们提供了handler机制,帮我们完成,接受子线程传来的数据,更新UI线程得作用,大大方便了我们的使用。并且在activity生命周期中,各个回调方法的调用中,也是用到了Handler机制,来调用各个回调方法。
        ps:作为知识回顾总结:
             创建线程的方式:
                                       一是,继承线程类Thread,并重写Run()
public class GetThread1 extends Thread{@Overridepublic void run() {super.run();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}

二是,实现接口Runable
public class GetThread2 implements Runnable{@Overridepublic void run() {}} 
三是,直接new Thread()
new Thread(new Runnable() {@Overridepublic void run() {   try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}mytext.setText("ffff");}}).start();

二 、正文Handler基本使用

Handler可以在子线程中,分发Message对象和Runable对象到主线程中,每个Handler实例,都会绑定到创建它的线程中(一般位于主线程)。
它的两个作用:(1)、 安排消息或Runnable 在某个主线程中某个地方执行, 
                          (2)、安排一个动作在不同的线程中执行


1、创建Handler对象方式:
(1)、直接new Handler()
 private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {viewPager.setCurrentItem(currentItem);// 切换当前显示的图片};};
(2)、继承Handler对象
  private Handler getapphandler = new getAppHandler();      class getAppHandler extends Handler{@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 1://queryAppInfo();break;case 2:getCompareAppInfos(isUserBigDate);break;default:break;}}}

2、Handler中分发消息的方法

        post(Runnable)
    postAtTime(Runnable,long)
    postDelayed(Runnable long)
   
    sendEmptyMessage(int)
    sendMessage(Message)
    sendMessageAtTime(Message,long)
    sendMessageDelayed(Message,long)
                    以上post类方法允许你排列一个Runnable对象到主线程队列中,
        sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.



发送Message:

     Message msg;
  发送一:
     msg = Message.obtain(getapphandler,2);///////获取message对象
     msg.sendToTarget();                   ///////发送message
     ----------------------------------------------------------------------
     Message msg = handler.obtainMessage();///////通过Handler获取message对象
     msg.what = xxx;
     msg.arg1  = xxx;
     msg.arg2  = xxx;
     msg.obj    = xxx;
     msg.sendToTarget(); ////发送


 发送二:
     Message msg = new Message()///////自己new message
     msg.what = xxx;
     msg.arg1  = xxx;
     msg.arg2  = xxx;
     handler.sendMessage(msg);////发送


     性能异同比较:
     建议以后创建Message对象时,使用Message msg = handler.obtainMessage();的形式创
     建Message,不要自己New Message。因为此法创建,Message创建第一次时,是new的,第二三次再次使用时,
     这里我们的Message 已经不是 自己创建的了,而是从MessagePool 拿的,省去了创建对象申请内存的开销。。。。。

     然而发送message,使用obtainMessage 或者是 sendMessage 效率影响并不大.

实例代码:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mytext=(TextView) findViewById(R.id.mytext);btn_post=(Button) findViewById(R.id.btn_post);btn_post.setOnClickListener(new MyOnclickListen());btn_stop=(Button) findViewById(R.id.btn_stop);btn_stop.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {//将线程对象从队列中移除  mhandler.removeCallbacks(mRunable);}});/** * 创建子线程,在java中有两种方法实现线程体: * 一是,继承线程类Thread * 二是,实现接口Runable */GetThread1 getThread1=new GetThread1();getThread1.start();/** * 三是 new Thread(new Runnable() {@Overridepublic void run() {   try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}mytext.setText("ffff");}}).start();*/}

public class GetThread1 extends Thread{@Overridepublic void run() {super.run();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}/** * 发送Message的方式: * 获取Message方式: * 第一种写法是message 从handler 类获取,从而可以直接向该handler 对象发送消息, * Handler中obtainMessage与new Message的区别:   obtainmessage()是从消息池中拿来一个msg 不需要另开辟空间new   new需要重新申请,效率低,obtianmessage可以循环利用; *  * 第二种写法是直接调用 handler 的发送消息方法发送消息。 *///第一种:obtainMessageMessage firstMessage=fristHandler.obtainMessage();firstMessage.obj="test1";firstMessage.sendToTarget();//第二种:sendMessage/*Message msg=new Message();msg.obj="test";Bundle b = new Bundle();// 存放数据            b.putString("color", "我的");msg.setData(b);fristHandler.sendMessage(msg);*/}}


  
 发送三:使用post(Runnable)


/**
* 调用Handler的post()方法,将要执行的线程对象放到队列当中  

* 这是android提供的一种机制,handler对象将通过post方法,
* 将里面的Runnable对象放到UI执行队列中,
* UI消费这个队列,调用Runnable的run方法。

* 虽然执行了new Runnable()这里并不生成新的线程。
* 因为Handler是绑定到UI主线程,Handler和UI主线程是同一个线程,
* HAndler的作用,主要是在其他后台线程中,通过handler这个媒介,
* 向UI主线程发送Runable对象。

*/
secondHandler.post(mRunable);
实例代码
private Runnable mRunable=new Runnable() {@Overridepublic void run() {   //为了方便 查看,我们用Log打印出来               Log.e(TAG, Thread.currentThread().getName() + " " +count);               count++;               setTitle("" +count);               btn_post.setText(""+count);            //每2秒执行一次               mhandler.postDelayed(mRunable, 2000);   }};

public class MyOnclickListen implements OnClickListener{@Overridepublic void onClick(View arg0) {/** * 调用Handler的post()方法,将要执行的线程对象放到队列当中   *  * 这是android提供的一种机制,handler对象将通过post方法, * 将里面的Runnable对象放到UI执行队列中, * UI消费这个队列,调用Runnable的run方法。 *  * 虽然执行了new Runnable()这里并不生成新的线程。 * 因为Handler是绑定到UI主线程,Handler和UI主线程是同一个线程, * HAndler的作用,主要是在其他后台线程中,通过handler这个媒介, * 向UI主线程发送Runable对象。 *  */mhandler.post(mRunable);}}
post参考:eg:http://byandby.iteye.com/blog/832467


三、Hander机制简介

1、Handler机制简述:

      1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
  2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;
                或者接收Looper从Message Queue取出)所送来的消息。
  3) Message Queue(消息队列):用来存放线程放入的消息。
  4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue


2、handler的原理:
handler封装了消息的发送,主要包括消息发送给谁。

1)、Looper:
activityThread创建Ui线程时,通过ThreadLocal.set(new Lopper),set了Looper对象,
a、内部包含了一个消息队列也就是messageQueue,所有handler发送的消息都走向了消息队列。
b、通过looper.looper方法,就是一个死循环,不断从messageQueue去消息,如果有消息就处理,没消息就阻塞。

2)、MessageQueue:
就是一个消息队列,可以添加消息,并处理消息。

3)、Handler:
handler构造函数内部会跟Looper进行关联,即通过上面的ThreadLocal.get()得到Looper对象,也就是说在handler的内部可以找到Looper,找到Looper也就找到MessageQueue,在handler中发送消息,其实就是向
handler负责发送消息,looper负责接收handler发送的消息,并直接把消息回传给hanndler自己。

4)、messageQueue就是一个存储消息的容器。
当你创建一个进程的时候,就回创建一个main线程,也就是activityThread线程,activityThread线程会在系统之中,
为我们创建默认去创建一个looper,Looper就回和MessageQuenen和UI线程,有联系。主线程运行MessageQuenene.



UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,
该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。
之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化
的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Handler、Looper、MessageQueue的初始化流程如图所示:

Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,
子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。

UI主线程通过Looper循环查询消息队列UI_MQ,
当发现有消息存在时会将消息从消息队列中取出。
首先分析消息,通过消息的参数判断该消息对应的Handler,
然后将消息分发到指定的Handler进行处理。

欧了!!!!!!!!!!!!!!!!



         
0 0
原创粉丝点击