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;//保存任意数据
public long when;//记录应该被处理的时间值
Handler target;//用来处理消息的Handler对象,就是发送消息的handler
Runnable callback; //用来处理消息的回调器(一般不用)
Message next;//指向下一个Message,用来形成一个链表
private static Message sPool; //用来缓存处理过的Message,以便复用
Message obtain() //该方法利用了Message中消息池(sPool)
Runnable的run()什么时候在分线程执行?
将Runnable传给Thread的构造方法:
new Thread(new Runnable(){
public void run(){//在分线程执行
}
}).start();
Handler: 发送消息 处理消息 移除消息
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);//延迟消息 延迟时间为0
}
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);//发送一个空的延迟消息
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {//发送不带数据的消息
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
//发送延迟消息,指定消息,指定延迟时间
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//当前时间+延迟时间
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
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, uptimeMillis);
}
//将消息添加到消息队列
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
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, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;//保存发送消息的handler对象
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);//调用消息队列保存消息对象
}
//移除消息
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);//调用消息队列移除它内部的指定what消息
}
//处理消息的回调方法
public void handleMessage(@NonNull Message msg) {
}
//
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) { //如果消息可以自己处理,让消息自己处理
handleCallback(msg);
} else {
if (mCallback != null) { //如果handler中有回调监听器(即callBack),调用回调器来处理消息
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); //让Handler的 handleMessage()来处理
}
}
MessageQueue:存储消息的以message的when排序的优先级队列
boolean enqueueMessage(Message msg, long when){}//将message添加到队列中
for (;;) { //将当前消息对象保存到消息队列中一个合适的位置
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
} //最终的结果是: 消息队列是按when来排序的
nativeWake(mPtr); //通过本地方法实现对处于等待状态的底层线程
// 取出一个合适的Message对象,可能不会立即返回
Message next() {
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);//本地方法,会导致可能处于等待状态,但不会阻塞主线程
Message msg = mMessages;//取出消息队列中的第一个消息
......
return msg;//返回
}
}
Looper 从MessageQueue中获取当前需要处理的消息,并交给Handler处理
//核心方法
public static void loop() {
final Looper me = myLooper(); //得到looper对象
final MessageQueue queue = me.mQueue; //得到消息队列对象
// 无限循环 没有break
for (;;) {
Message msg = queue.next(); // 从消息队列中取出消息 might block(可能阻塞)
......
msg.target.dispatchMessage(msg); //调用Handler去分发并处理消息
msg.recycleUnchecked(); //回收利用message
}
}
消息机制与异步任务总结
在Android中,只有在UIThread(主线程)中才能直接更新页面
在Android中长时间的工作(联网)都需要在worker Thread中执行
在分线程获得服务器数据后,需要立即到主线程中去更新界面显示数据
如何实现线程间通讯?
1)消息机制:Handler + Thread
2)异步任务: AsyncTask == Handler + ThreadPool
相关API
Message
Message(消息):
线程间通信的数据载体
1) 对象的创建
Message.obtain() //有可能是新建的,也有可能是复用的消息池中的
2)对象的使用
使用相对较频繁的
int what //标识
int args1//存储整形数据
int args2//存储+整形数据
Object obj //存储任意类型(对象)数据
使用不频繁的
Handler target //保存处理消息的handler对象(发消息的handler)
long when //消息应该被处理的时间
Message next //有了此属性Message就可以形成队列
static Message pool //消息池,缓存用过得消息用于复用
Runnable CallBack // 用来处理当前消息的回调器
Handler的使用
Handler // 发送 处理 移除消息
1)对象的创建
new Handler()
- 对象的使用
发送消息
发即时消息:sendMessage(Message message)
发延迟消息:sendMessageDelayed(Message message,long delayTime)
发即时空消息:sendEmptyMessage(int what) //发送内容为空
发延迟空消息:sendEmptyMessageDelayed(int what,long delayTime)
处理消息
void handleMessage(Message msg) //回调方法
移除消息
removeMessage(int what) //移除未处理的指定what的message
removeCallbacksAndMessages(@Nullable Object token) // 传null【removeCallbacksAndMessages(null)】移除所有未处理的消息
MessageQueue :消息队列
用来存放通过Handler发送的消息
它是一个按Message的when排序的优先级队列
Looper(钩子) 循环器
负责循环取出MessageQueue里面的当前需要处理的Message
交给对应的Handler进行处理
处理完后,将Message缓存到消息池中,以备复用
消息机制的原理
image.png image.pngHandler用于做什么工作?
1.线程间通信(子线程切换到主线程运行)
2.延迟的工作
3.循环定时工作
AsyncTask的使用
1.什么是异步任务?
逻辑上:以多线程的方式完成的功能需求
API上:指AscyncTask
AsyncTask的理解
1)在没有它之前我们可以用Handler+Thread实现一个异步任务的功能
2)使用AsyncTask也可以实现异步功能
为什么使用AsyncTask
1.编码简洁(可以理解为填空题(Async)和问答题的区别)
2.运行效率高:线程池
相关API:
Async的基本原理
image.pngJSON
1.JSON是什么?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式
本质就是具有特定格式的字符串
JSON数据已经是客户端与服务器端交互
的最常用的选择,已经很少使用xml来进行数据交互了
json与xml比较的优势:
简洁 小(省流量、响应快)
2.JSON的数据格式
整体结构:
Json数组:[ ]
Json对象:{ }
Jso数组的结构:[value1,value2,value3]
Json对象的结构:{key1:value1,key2:value2,key3:value3}
key的数据类型:字符串
value的数据类型:
数值
字符串
null
json数组[]
json对象{}
例子:
[1,"ab",[],{"n":123,"b":"abc"}]
{"name":"TOM","age":12}
image.png
3.如何解析JSON
解析技术:
Android原生API:编程相对麻烦
Gson框架:编码简洁,项目首选
解析方向:
将java对象(包含集合)转换为json格式字符串(服务器)
将json格式字符串转化为java对象(包含集合)
相关API
image.png对象根据Key取value 数组根据下标取值
网友评论