位置: 编程技术 - 正文

android中Handler学习心得(安卓handler使用)

编辑:rootadmin

推荐整理分享android中Handler学习心得(安卓handler使用),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:android handler用法,android handle原理,android handle原理,安卓中handler作用,android中handler机制,android中handler机制,android handler用法,android handler用法,内容如对您有帮助,希望把文章链接给更多的朋友!

在android开发中,Handler消息发送和处理几乎无处不在。稍微复杂一点的Activity,需要运行时更新UI一般都会使用Handler,特别是在非UI线程中更新UI必须使用Handler(除了极个别View可以在线程中更新)发送消息,然后在Handler.handleMessage()中接收到,处理消息更新UI。Activity.runOnUiThread()也是可以更新UI,其实也是间接使用了handler的。

如果一不小心,在非UI线程中直接更新UI会抛出异常,程序直接关闭,错误消息如下:

- ::.: E/AndroidRuntime(): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

一般在Activity中申明一个handler对象,然后在异步处理的地方使用该handler.sendMessage()一个消息,然后在handler的handleMessage方法里进行判断处理。

Handler里有很多发送消息的方法,可以实现各种需求:

sendMessage(Message msg)

sendEmptyMessage(int what)

sendEmptyMessageDelayed(int what, long delayMillis)

sendEmptyMessageAtTime(int what, long uptimeMillis)

sendMessageDelayed(Message msg, long delayMillis)

sendMessageAtFrontOfQueue(Message msg)

sendMessageAtTime(Message msg, long uptimeMillis)

通过以上的方法发送的消息,可以在msg.callback方法中更新UI,或 handleMessage(Message)中接收到,然后可以更新UI。

post(Runnable r)

postAtTime(Runnable r, long uptimeMillis)

postAtTime(Runnable r, Object token, long uptimeMillis)

postDelayed(Runnable r, long delayMillis)

postAtFrontOfQueue(Runnable r)

通过以上方法可以传递一个实现了Runnable接口的对象,在该对象的run()方法里可以更新UI。

通过关联的源代码,可以发现,Handler有构造方法如下:

public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }

若传入了looper对象,会调用该构造方法。

可以看出Handler收发消息需要借助这两个对象:Looper,MessageQueue;asynchronous是否是异步接收消息,该方法的注释可以大致知道,使用默认的Looper来handleMessage将不会是异步的,所以是false,Callback接口里面只有一个方法,其实就是handleMessage()处理消息的回调函数,为null时,直接使用Handler自身的handleMessage()方法。

当在申明handler的时候根本没有传入Looper?

在另外的一个构造方法中源码如下:

mLooper = Looper.myLooper(); if (mLooper == null) {

throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;

若没有传looper,直接使用Looper.myLooper()获取,即返回的是Looper中sThreadLocal变量中的looper;在Activity启动时,默认会创建一个looper,在ActivityThread类里面有申明的 final Looper mLooper = Looper.myLooper(),在Activity.attach(....)方法中可以看到ActivityThread对象被传入。如果在UI线程中申明Handler,默认用到的就是这个mLooper。

先来看看消息是怎么发送的?大致理解:

通过handler的构造函数 知道了有个MessageQueue,字面意思知道里面放的全是Message了,看源码本来就是。mQueue就是在Looper里面维护,是在Looper的构造方法中new出来的,源码如下:

private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();}

android中Handler学习心得(安卓handler使用)

该构造方法是私有构造,只有Looper自身才能调用,当外界调用prepare()方法时,间接的去new Looper(),并放入到sThreadLocal中:

public static void prepare() { prepare(true);}

private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));}

new时需要传入一个boolean类型的参数quitAllowed,参数主要用于new MessageQueue(quitAllowed),字面意思是允许退出,默认传入的是true,当调用

public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }

上面方法传入的是false。理解为当UI线程(mainThread)开启Looper时传入的是false,其他子线程传入的true。

上面那么多发送消息的方法,最后都会调用到sendMessageAtTime()方法,源码如下:

public boolean sendMessageAtTime(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);}

接着调用了enqueueMessage()方法,源码如下:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}

可以看到msg.target=this,消息里还保存了Handler对象的引用。 通过MessageQueue.enqueueMessage()最终把要发送的消息放入队列中,等待发送。

接着看看消息是怎么接收的?

Looper是什么,MessageQueue又是什么?通过看源码可以大致理解:

Looper就是不断的到MessageQueue拿Message然后dispatchMessage到handleMessage();源码如下:

public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " &#; msg.target &#; " " &#; msg.callback &#; ": " &#; msg.what); } msg.target.dispatchMessage(msg);

…………

…………

}

首先拿到当前线程的Looper对象me,然后拿到MessageQueue对象queue=me.mQueue,再然后就是for循环了,不断的拿Message msg = queue.next(); 然后就是msg.target.dispatchMessage(msg)分发消息,上面说了msg.target就是handler,又回到了handler对象中了; dispatchMessage(Message msg)方法源码如下:

public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }

优先使用msg.callback,其次是构造方法传过来mCallback,最后才使用自身的handleMessage。此时正在更新UI。

通过上面知道,若要在子线程中要申明一个handler对象,并要收发消息,有两种方式:第一种:在run()方法中,先要调用Looper.prepare()方法(间接的new Looper(),间接的new MessageQueue()),接着不停的sendMessage,最后必须调用Looper.loop(),才能把消息拿出并dispatchMessage。第二种:在申明handler的时候把UI线程中的Looper对象传入,不需重新创建新的Looper及MessageQueue对象,例如:Handler handler = new Handler(Looper.getMainLooper()){public void handleMessage(Message msg){//handle message}};或Handler handler = new Handler(Looper.getMainLooper(),new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {//handle messagereturn false;}});

这种方式不需要再调用prepare和loop了,直接发消息就可以了。原因是:调用prepare就是用来new Looper()和new MessageQueue(),而现在已经传入了一个looper自然不需要再new了;调用loop主要用于开启消息循环不断到MessageQueue拿消息的,现在传入的是MainThread的mLooper,上面有说到在创建MainThread的looper时传入的boolean型变量是false即该looper对象中的mQueue不允许退出,猜测loop一直在执行中即使mQueue中没有消息也不会退出,当有消息发送过来时就拿出来并dispatchMessage。

MessageQueue 中的quit方法源码如下:

void quit(boolean safe) { if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowed to quit."); }

……

……

}

至于该方法在哪里调用还没弄明白,而且关于Handler还有很细节问题没搞清楚,有待提高。

Android UI之TableLayout(表格布局) 说明:表格布局采用常见的表格方式来表示布局,与上文中提到的android:weight属性显示出来的效果有些相似。而事实上,TableLayout的确是LinearLayout的子类

asm/semaphore.h: No such file or directory 当我进行内核hook的时候,包含的#includeasm/semaphore.h头文件,编译的时候系统提示找不到这个文件或者目录,然后去谷歌搜的,上面说这个头文件已经被

Android学习 - Android新的menu实现ActionMode Android的menu有多种实现方式,这里介绍一种新的menu实现方式:ActionMode。ActionMode是Android3.0以后出现的,我们可以使用AppCompat库使ActionMode兼容至Android2.1。

标签: 安卓handler使用

本文链接地址:https://www.jiuchutong.com/biancheng/378169.html 转载请保留说明!

上一篇:Android roboguice 开源框架使用

下一篇:Android UI之TableLayout(表格布局)

  • 出口退税便捷退税操作流程
  • 收到增值税发票是不是就给钱了
  • 所得税申报资产不允许为0?
  • 小规模免哪些税
  • 收到服务费发票摘要怎么写
  • 个人社保由单位承担的可以进福利费吗
  • 发放股票股利增资
  • 资产类期末借方余额怎么算
  • 发生非正常损失的购进货物不准予抵扣的增值税
  • 月末应付职工薪酬计算方法
  • 劳服企业可以安差额税上税吗?
  • 什么时候需要计算环境熵变
  • 税收滞纳金和税金滞纳金有什么区别
  • 一般纳税人能开普票吗,几个点
  • 银行承兑贴息率是年利率吗
  • 商品流通企业代表企业
  • 增值税一般纳税人与小规模纳税人的区别
  • 1697509422
  • 苗木公司经营理念
  • 出口转内销的销项税怎么计算
  • u盘启动器安装系统
  • 原材料进口关税计入成本吗
  • win10任务栏快捷图标不见了
  • ampa.exe是什么
  • sccenter.exe - sccenter是什么进程 有什么用
  • php面向对象面试题
  • 赖格宝视频
  • 外商投资工业企业有哪些
  • 收到借款利息会计科目
  • pdo_mysql
  • 注册资本和投资总额的关系
  • 补缴去年的工会经费计提
  • vit详解
  • 基于强化学习的智能机器人路径规划算法研究(附代码)
  • b站怎么进抖音模式
  • cvpr2020目标跟踪
  • 删除ont命令
  • python中模块的用法
  • 进项发票无法取消怎么办
  • 财务报表季报应付职工薪酬是指三个月工资累计还是
  • 化工企业 设备
  • 建安类企业包括哪些公司
  • 一次性用品可以做什么东西
  • 税控盘服务费抵减增值税如何申报
  • 结转成本类账户及税金及附加到本年利润
  • 下列项目的进项税额可以从销项税额中抵扣的是()
  • 工资是什么?包括哪些
  • 营业执照是什么字体
  • 公司厨房用具
  • 库存现金日记账怎么填
  • 工程一般挂靠取得的收入怎么做账?
  • 房屋租赁合同怎么写对房东有利
  • 同一张发票报销两次会被发现吗
  • 累计折旧的计提会计分录
  • 小规模纳税人能开专票吗2023
  • 资产负债表日指的是什么
  • sql中的存储过程
  • Linux(Ubuntu)下mysql5.7.17安装配置方法图文教程
  • win8激活点不进去
  • 调整服务能力的策略不包括什么
  • ubuntu系统无法安装中文
  • ubuntu修改ip地址方法
  • ubuntu独立显卡黑屏
  • win8系统升级
  • 新款苹果笔记本测评
  • linux安装编译工具
  • rhel7提供的5种基本安装方式是
  • 在linux操作系统中
  • windows10运用
  • unity 移动应用开发
  • Shell脚本监控日志 出现关键字 grep提醒
  • javascript数据类型有哪些
  • Unity3D游戏开发(第2版)
  • jquery js区别
  • jQuery AJAX timeout 超时问题详解
  • 国税局事业编制和公务员哪个比较好
  • 河北省国家税务总局云办税厅
  • 内蒙地税个人所得税标准
  • 湖南电子税务申报
  • 税收优惠政策有没有政府补助
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设