Android的线程通信:消息机制原理(Message,Handler,MessageQueue,Looper),异步任务AsyncTask,使用JSON

背景

在Android中,只有在UIThread中才能直接更新界面
在Android中,长时间的工作(联网)都需要在workerThread中执行
在分线程获得服务器数据后, 需要立即到主线程去更新界面显示数据(这就需要通信)
如何实现线程间通信呢?
	下面我们来了解:Android里面的消息机制和异步任务

API

Message :消息
	可理解为线程间通讯的数据单元, 可通过message携带需要的数据
	创建对象:  Message.obtain(what)	
	封装数据
		public int what    //id 标识
		public int arg1
		public int arg2
		public Object obj
Handler : 处理器
	Handler是Message的处理器,同时也负责消息的发送和移除的工作
	发送即时消息:  sendMessage(Message msg)
	发送延时消息:  sendMessageDelayed(Message msg, long time)//延迟处理,不是延迟发送,也会立即发送的
	处理消息: handleMessage(Message msg)    (回调方法)
	移除还未处理的消息: removeMessages(int what)
MessageQueue : 消息队列
	用来存放通过Handler发送的消息
	它是一个按Message的when排序的优先级队列
Looper(钩子) : 循环器
	负责循环取出Message Queue里面的当前需要处理的Message
	交给对应的Handler进行处理
	处理完后, 将Message缓存到消息池中, 以备复用

消息机制原理

图解

在这里插入图片描述
在这里插入图片描述

Message

/*
 * Message类:
 * 		public int what; id标识
 * 		public int arg1; 保存int的数据
 * 		public int arg2; 保存int的数据
 * 		public Object obj;保存任意数据
 * 		long when; 记录应该被处理的时间值
 * 		Handler target; 用来处理消息的Handler对象,就是保存用来发送消息的Handler
 * 		Runnable callback; 用来处理消息的回调器
 * 		Message next; 下一个Message,形成链表的结构
 * 		private static Message sPool; 用来缓存处理过的Message,用来复用
 * 		
 * 		Runnable对象的run()什么时候在分线程执行?
 * 			将Runnable传给Thread的构造方法的时候,比如:
 * 			new Thread(new Runnable(){
 * 				public void run(){} //这个就是在分线程执行
 * 			}).start();
 */

Handler

/*
 * Handler类:
 * 	作用:发送消息,处理消息,移除消息
 * 		sendMessage(Message msg)  调用sendMessageDelayed(msg, 0);
 * 		
 * 		sendEmptyMessage(int what) 调用 sendEmptyMessageDelayed(what, 0);
 * 		进入里面看
 * 		    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
		        Message msg = Message.obtain();
		        msg.what = what;
		        return sendMessageDelayed(msg, delayMillis);
		    }
		其实发送空消息就是发送不带数据的消息
		
		上面调用最多的就是sendMessageDelayed(Message msg, long delayMillis),进入查看一下
		
			    public final boolean sendMessageDelayed(Message msg, long delayMillis)
			    {
			        if (delayMillis < 0) {
			            delayMillis = 0;
			        }
			        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
			    }
		所以发送延迟消息就是发送的当前时间加上延迟的时间
		进入sendMessageAtTime这个方法查看
				    public final boolean sendMessageAtFrontOfQueue(Message msg) {
				        MessageQueue queue = mQueue;
				        if (queue == null) {
				            RuntimeException e = new RuntimeException(
				                this + " sendMessageAtTime() called with no mQueue");
				            Log.w("Looper", e.getMessage(), e);
				            return false;
				        }
				        return enqueueMessage(queue, msg, 0);
				    }
		进入enqueueMessage(queue, msg, 0);
			    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
			    	//这个就是将消息的target设置成当前的Handler,就是发送消息的Handler
			        msg.target = this;
			        if (mAsynchronous) {
			            msg.setAsynchronous(true);
			        }
			        //然后调用了消息队列里面的方法将消息加入消息队列
			        return queue.enqueueMessage(msg, uptimeMillis);
			    }
		
		移除消息
		    public final void removeMessages(int what) {
		        mQueue.removeMessages(this, what, null);
		    }
		 处理消息,需要重写的
		 	    public void handleMessage(Message msg) {
    			}
    			
    	派发消息
    	 public void dispatchMessage(Message msg) {
    	 	//如果消息自己可以处理,就让消息自己处理,就是看消息有没有重写callback方法
	        if (msg.callback != null) {
	            handleCallback(msg);
	        } else {
	        	//如果Handler对象中有回调监听器,调用回调监听器来处理消息,
	        	//回调监听器如果返回的是true,就会处理完毕,比如又会继续调用handleMessage
	            if (mCallback != null) {
	                if (mCallback.handleMessage(msg)) {
	                    return;
	                }
	            }
	            handleMessage(msg);
	        }
	    }
 */

MessageQueue

/*
    MessageQueue类:这是储存消息的队列,以message的when排序的优先级队列
    	enqueueMessage(Message msg, long when)//将message添加到队列中
    	里面的队列排序的原理也很简单,可以查看一下
    		    boolean enqueueMessage(Message msg, long when) {
			        if (msg.isInUse()) {
			            throw new AndroidRuntimeException(msg + " This message is already in use.");
			        }
			        if (msg.target == null) {
			            throw new AndroidRuntimeException("Message must have a target.");
			        }
			
			        boolean needWake;
			        synchronized (this) {
			            if (mQuiting) {
			                RuntimeException e = new RuntimeException(
			                        msg.target + " sending message to a Handler on a dead thread");
			                Log.w("MessageQueue", e.getMessage(), e);
			                return false;
			            }
			
			            msg.when = when;
			            Message p = mMessages;
			            if (p == null || when == 0 || when < p.when) {
			                // New head, wake up the event queue if blocked.
			                msg.next = p;
			                mMessages = msg;
			                needWake = mBlocked;
			            } else {
			                // Inserted within the middle of the queue.  Usually we don't have to wake
			                // up the event queue unless there is a barrier at the head of the queue
			                // and the message is the earliest asynchronous message in the queue.
			                needWake = mBlocked && p.target == null && msg.isAsynchronous();
			                Message prev;
			                for (;;) {
			                    prev = p;
			                    p = p.next;
			                    if (p == null || when < p.when) {
			                        break;
			                    }
			                    if (needWake && p.isAsynchronous()) {
			                        needWake = false;
			                    }
			                }
			                msg.next = p; // invariant: p == prev.next
			                prev.next = msg;
			            }
			        }
			        if (needWake) {
			            nativeWake(mPtr);
			        }
			        return true;
			    }
			    
		取出一个Message对象,但是可能不会立即返回
		Message next()	里面取出消息队列中的第一个消息,然后返回
		    里面调用了nativePollOnce(mPtr, nextPollTimeoutMillis);方法
		    		这个本地方法会导致处于处理等待状态,但是不会阻塞主线程
 */

Looper

	Looper类:这个方法在系统启动的时候就启动了
		作用是从MessageQueue中获取当前需要处理的消息,并交给Handler处理
		
		    public static void loop() {
   
   
		    	//获取当前的钩子
		        final Looper me = myLooper();
		        //获取消息队列
		        final MessageQueue queue = me.mQueue;
		        for (;;) {
   
   
		        	//这里虽然是无限for循环,但是这个获取下一个消息可能会处于阻塞状态
		            Message msg = queue.next(); // might block
					//调用Handler去分发消息并且处理消息
		            msg.target.dispatchMessage(msg);
					//回收利用消息
		            msg.recycle();
		        }
		    }

异步任务AsyncTask

简介

什么是异步任务?
	逻辑上: 以多线程的方式完成的功能需求
	API上: 指AsyncTask类

AsyncTask的理解
	在没有AsyncTask之前, 我们用Handler+Thread就可以实现异步任务的功能需求
	AsyncTask是对Handler和Thread的封装, 使用它更编码更简洁,更高效
	AsyncTask封装了ThreadPool, 比直接使用Thread效率要高

API


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReflectMirroring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值