现在的位置: 首页 > 综合 > 正文

浅谈Handler

2018年06月05日 ⁄ 综合 ⁄ 共 6198字 ⁄ 字号 评论关闭

 浅谈Handler

一、前言

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

二是,实现接口Runable

public class GetThread2 implements Runnable{

		@Override
		public void run() {
			
		}
	} 

三是,直接new Thread()

new Thread(new Runnable() {
			
			@Override
			public void run() {
			   try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.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{
		@Override
		public 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 效率影响并不大.

实例代码:
@Override
	protected 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() {
			
			@Override
			public void onClick(View arg0) {
				//将线程对象从队列中移除  
				mhandler.removeCallbacks(mRunable);
			}
		});
		/**
		 * 创建子线程,在java中有两种方法实现线程体:
		 * 一是,继承线程类Thread
		 * 二是,实现接口Runable
		 */
		
		GetThread1 getThread1=new GetThread1();
		getThread1.start();
		
		

		/**
		 * 三是
		 
		new Thread(new Runnable() {
			
			@Override
			public void run() {
			   try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				mytext.setText("ffff");
			}
		}).start();
		
		*/
		
	}

public class GetThread1 extends Thread{
		
		@Override
		public 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 的发送消息方法发送消息。
			 */
			//第一种:obtainMessage
			Message 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() {
			
		@Override
		public 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{
		

		@Override
		public 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进行处理。


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


         

抱歉!评论已关闭.