当前位置: 首页 > news >正文

太原中小学网站建设个人推广平台

太原中小学网站建设,个人推广平台,淘宝上做网站的信得过吗,长春 美容 网站建设一 概述Handler主要被用来在子线程中访问UI线程,在ViewRootImpl中有一个checkThread()方法,对UI的操作都会有此验证。所以操作UI只能在主线程中进行。概念:Handler的运行由底层MessageQueue和Looper支撑。MessageQueue消息队列,单…

一 概述

Handler主要被用来在子线程中访问UI线程,在ViewRootImpl中有一个checkThread()方法,对UI的操作都会有此验证。所以操作UI只能在主线程中进行。

概念:

Handler的运行由底层MessageQueue和Looper支撑。

MessageQueue消息队列,单链表存储消息列表。它是消息的存储单元。

Looper循环,它会无限循环查找是否有消息,有就处理掉。Looper创建一般被保存在TheadLoacal中。

创建:

Handler创建采用当前线程的Looper来构造消息循环系统。线程默认没有Looper

主线程(UI线程)即:ActivityThread,主线程创建时会初始化Looper,所以主线程可直接使用Handler

二 运行机制

2.1 TheadLoacal

TheadLoacal的用来保存数据,以线程作用域,不同线程具有不同的数据副本。

以一个例子来简单粗暴的说明:

//定义一个Integer泛型的ThreadLocal

private ThreadLocal mIntTheadLocal = new ThreadLocal();

mIntTheadLocal.set(0);

Log.d("yink","UI Thead, mIntTheadLocal = " + mIntTheadLocal.get());//UI线程

new Thread("thead 1") {

@Override

public void run() {

mIntTheadLocal.set(1);

Log.d("yink","thead 1, mIntTheadLocal = " + mIntTheadLocal.get());//线程1

}

}.start();

new Thread("thead 2") {

@Override

public void run() {

Log.d("yink","thead 2, mIntTheadLocal = " + mIntTheadLocal.get());//线程2

}

}.start();

mIntTheadLocal是同一个对象,我们分别在UI线程、线程1和线程2中对其进行set,get并打印Log如下:

07-06 23:24:33.151 12661-12661/com.example.android.myapplication D/yink: UI Thead, mIntTheadLocal = 0

07-06 23:24:33.153 12661-16454/com.example.android.myapplication D/yink: thead 1, mIntTheadLocal = 1

07-06 23:24:33.154 12661-16455/com.example.android.myapplication D/yink: thead 2, mIntTheadLocal = null

由于TheadLoacal的特性,它其中之一的功能就是被用来保存Looper对象

2.2 MessageQueue

MessageQueue,单链表数据结构,主要包含两个操作:插入(enqueueMessage)和读取(next)

先看enqueueMessage,它之做了单链表插入数据操作

boolean enqueueMessage(Message msg, long when) {

...

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;

}

...

}

再看next,查询到msg后,移除这个msg,并返回这个msg

Message next() {

...

if (msg != null && msg.target == null) {

// Stalled by a barrier. Find the next asynchronous message in the queue.

//被阻塞,在队列中查询下一个消息

do {

prevMsg = msg;

msg = msg.next;

} while (msg != null && !msg.isAsynchronous());

}

if (msg != null) {

if (now < msg.when) {

// Next message is not ready. Set a timeout to wake up when it is ready.

nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);

} else {

// Got a message.

mBlocked = false;

//msg不为空,移除msg

if (prevMsg != null) {

prevMsg.next = msg.next;

} else {

mMessages = msg.next;

}

msg.next = null;

if (DEBUG) Log.v(TAG, "Returning message: " + msg);

msg.markInUse();

//返回msg

return msg;

}

} else {

// No more messages.

nextPollTimeoutMillis = -1;

}

...

}

2.3 Looper

Looper作用:不停的从MessageQueue中查询是否有消息,有就处理,没有就一直阻塞。

我们先来一个demo,为子线程创建Looper,来理解Looper的作用:

//主线程中定义

private Handler mHandler;

new Thread("Thread 1") {

@Override

public void run() {

//创建Looper

Looper.prepare();

//在Thread 1中创建Handler

mHandler = new Handler(){

@Override

public void handleMessage(Message msg) {

Bundle b = new Bundle();

b = msg.getData();

Log.d("yink","receive the number = " + b.getInt(KEY));

switch (b.getInt(KEY)) {

case 3:

//子线程处理完事情后,退出循环

//Looper还提供一个quitSafely(),这个方法是设置标记位,把队列中消息处理完后再退出。

getLooper().quit();

break;

default:

break;

}

super.handleMessage(msg);

}

};

//循环,关键函数

Looper.loop();

}

}.start();

new Thread("Thread 2") {

@Override

public void run() {

for (int i = 0 ; i < 5 ; i++) {

Message msg = new Message();

Bundle b = new Bundle();

b.putInt(KEY,i);

msg.setData(b);

//如果线程1的run没执行的话,mHandler还是null,所以加个判断

if (mHandler != null) {

Log.d("yink","send key i = " + i);

//发送消息

mHandler.sendMessage(msg);

} else {

Log.d("yink","mHandler is null, i = " + i);

}

SystemClock.sleep(1000);

}

}

}.start();

结果如下:

07-07 02:29:24.219 1151 12404 D yink : send key i = 0

07-07 02:29:24.220 1151 12403 D yink : receive the number = 0

07-07 02:29:25.221 1151 12404 D yink : send key i = 1

07-07 02:29:25.223 1151 12403 D yink : receive the number = 1

07-07 02:29:26.223 1151 12404 D yink : send key i = 2

07-07 02:29:26.223 1151 12403 D yink : receive the number = 2

07-07 02:29:27.225 1151 12404 D yink : send key i = 3

07-07 02:29:27.226 1151 12403 D yink : receive the number = 3

07-07 02:29:28.227 1151 12404 D yink : send key i = 4

07-07 02:29:29.231 1151 12404 D yink : send key i = 5

ActivityThread中的Looper比较特殊,它的创建是:prepareMainLooper(),获得:getMainLooper,可在任何地方获取到主线程的Looper

接下来我们来看Looper中最重要的loop()方法:

public static void loop() {

...

for (;;) {

//无限循环获取queue.next(),由前面描述的MesageQueue的next方法,只有获取到消息才会返回,否则一直会阻塞,所以looper也会在这里阻塞

Message msg = queue.next(); // might block

if (msg == null) {

// No message indicates that the message queue is quitting.

//只有当Looper调用退出后,queue.next()才会返回null,因为不退出,MesageQueue会阻塞在那儿一直查询

//此无限循环中,只有当msg == null才退出循环

return;

}

...

try {

//target实际就是Handler,所以最终调用到创建Handler线程中去。

msg.target.dispatchMessage(msg);

}

....

2.4 Handler

Handler主要也是两个动作:发送和接收

先看发送:

public final boolean sendMessage(Message msg){

return sendMessageDelayed(msg, 0);

}

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {

Message msg = Message.obtain();

msg.what = what;

return sendMessageDelayed(msg, delayMillis);

}

public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {

Message msg = Message.obtain();

msg.what = what;

return sendMessageAtTime(msg, uptimeMillis);

}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

msg.target = this;

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

发送过程最后调用到了enqueueMessage,最后是向队列中插入了一条消息。

最后通过Looper返回给了Handler的dispatchMessage,转向接收处理。

public void dispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) {

return;

}

}

handleMessage(msg);

}

}

第一种接收if (msg.callback != null) :

如果msg.callback != null成立,则调用handleCallback(msg)来处理

private static void handleCallback(Message message) {

message.callback.run();

}

这个callback其实就是Handler.post中的runable

post过程如下:

public final boolean post(Runnable r)

{

return sendMessageDelayed(getPostMessage(r), 0);//调用getPostMessage

}

private static Message getPostMessage(Runnable r) {

Message m = Message.obtain();

m.callback = r;//把post中的Runnable赋值给msg.callback

return m;

}

证实:

new Thread("Thead 1") {

@Override

public void run() {

Looper.prepare();

mHandler = new Handler(){

@Override

public void handleMessage(Message msg) {

Log.d("yink","handleMessage ");

super.handleMessage(msg);

}

@Override

public void dispatchMessage(Message msg) {

Log.d("yink","dispatchMessage ");

super.dispatchMessage(msg);

}

};

Looper.loop();

}

}.start();

new Thread("Thead 2") {

@Override

public void run() {

mHandler.post(new Runnable() {

@Override

public void run() {

Log.d("yink","post runable");

}

});

}

}.start();

log如下,先是调用那个dispatchMessage然后走到调用了message.callback.run();

07-07 03:42:43.862 10475 10515 D yink : dispatchMessage

07-07 03:42:43.862 10475 10515 D yink : post runable

第二种接收else:

如果 if (mCallback != null) 则调用mCallback.handleMessage(msg)

这里的mCallBack为:

public interface Callback {

public boolean handleMessage(Message msg);

}

//Handler的一个构造函数

public Handler(Callback callback) {

this(callback, false);

}

可以在创建Handler的时候传递进来,这样就可以回调监听。就是一个接口回调,这里就不举例了。

如果mCallback == null就调用handleMessage,在源码中handleMessage是一个空函数,可以继承Handler实现handleMessage方法来进行监听。Looper中的demo就是实现handleMessage方法实现监听的。也可继承Handler实现,道理相同

//Handler中的handleMessage方法,一个空函数

public void handleMessage(Message msg) {

}

总结

Android的消息机制整体来说也就是Handler的消息机制,Handler、Looper和MessageQueue三者结合,实现了线程间的通信。明白这种机制,使用更加如鱼得水。

Read the fucking source code!

http://www.lbrq.cn/news/2666143.html

相关文章:

  • 济南做网站需要多少钱鸡西seo
  • 如何做英文网站外链推广app用什么平台比较好
  • 欢迎访问中国建设银行网上银行网站最新新闻事件今天国内大事
  • phpcms移动端网站怎么做如何查看网站权重
  • 做ppt的兼职网站有哪些网站制作公司排行榜
  • 网站的简介怎么在后台炒做灰色关键词排名收录
  • 怎么做点击图片跳转网站网络营销软件网站
  • 如何给自家网站做关键词优化建立一个国外的网站
  • 赣州网站建设在线超级外链工具
  • 开发区人才市场招聘信息最新招聘郑州企业网站优化排名
  • 网站建设市场多大百度seo优化排名客服电话
  • 网站怎么做才不会被墙近期新闻热点大事件
  • 罗湖网站建好网站制作公司
  • 横沥镇做网站百度首页推荐关不掉吗
  • 做一家网站要多少钱公司推广
  • 做字的网站公司企业网站模板
  • 服务器网站建设维护合同竞价培训课程
  • 网页设计实训体会网站优化排名软件推广
  • 企业网站建设后需要单独服务器关键词seo排名怎么选
  • 宽屏网站宽度网站设计专业的公司
  • 临汾哪做网站网上推广平台有哪些
  • wordpress搬家到本地网站优化的方式有哪些
  • 自己做网站的给微信取个什么名字好爱站网关键词挖掘工具熊猫
  • 有自己域名主机怎么做网站网络推广工作能长久吗
  • 公司网站开发制作网络推广费用高吗
  • 商丘建网站爱站查询工具
  • 做外贸怎么登陆国外网站如何自己做网络推广
  • php做不了大型网站关键词的选取原则
  • 合肥做网站价格太原seo关键词优化
  • 短网站生成万网商标查询
  • 精准计算Word文档页数的PHP类
  • 从Redisson源码角度深入理解Redis分布式锁的正确实现
  • react 常用组件库
  • Day37--动态规划--52. 携带研究材料(卡码网),518. 零钱兑换 II,377. 组合总和 Ⅳ,57. 爬楼梯(卡码网)
  • 2025年SEVC SCI2区,基于深度强化学习与模拟退火的多无人机侦察任务规划,深度解析+性能实测
  • 多级缓存详解