位置: 编程技术 - 正文

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(表格布局)

  • 税务行政诉讼是由税务机关进行审理并作出裁决
  • 养殖合作社属于什么行业
  • 保险经纪公司要取得什么证
  • 发票复印件盖公章
  • 公司清算后资产负债表与利润表
  • 核定征收企业可以申请高新技术
  • 以现金形式发放的福利怎么入账
  • 进项转出再差额征收待抵扣
  • 债转股企业所得税资本公积
  • 以前年度损益调整属于哪类科目
  • 降库存的方案
  • 工会经费的纳税依据
  • 没有成立工会的企业要交工会筹备金吗
  • 视同销售收入和成本如何确认
  • 向境外支付违约金要代扣税吗
  • 增值税是什么鬼
  • 母公司如何将子公司转让
  • 支付青苗补偿费怎么做账
  • 一般纳税人普通发票跨月冲红流程
  • 购买原材料的运费属于什么费用
  • 工会经费该怎么交
  • 行政单位年底结账怎么算
  • 监控 固定资产
  • 办公室椅子固定
  • 考试资格的工作有哪些
  • 光纤测速网速测试
  • 固定资产计提完折旧怎么处理
  • 应交税金减免税款
  • 物流公司的收入来源有哪些
  • 来料加工方式中,料件和加工后成品的所有权
  • 在网上怎
  • 股份支付如何缴纳个人所得税?
  • chrome新建标签为打开特定网页
  • 大雾山国家公园在哪里
  • 详解16型人格
  • stat命令的作用
  • 企业怎么可以合理避税?
  • 帝国cms怎么用
  • 企业成本核算应遵循
  • 怎样合理的运用网络
  • 企业之间收的借款利息该如何交税 原文
  • 货币捐赠会计分录
  • 一般纳税人内账考虑税额吗
  • 个人代扣代缴社保分录
  • 国际货运代理可以分哪几类?
  • 减值准备为什么不影响影响资产余额
  • sqlserver无法打开备份设备
  • sql 集合运算符
  • 返利冲减销售收入还是进费用
  • 事业单位无形资产包括
  • 个税异地缴纳后果
  • 关联公司代缴社保劳动者怎么处理
  • 年终奖能算在工资里吗
  • 资产负债表里包括应付利息吗
  • 收到保险公司保险费会计分录
  • 单价合同如何计算印花税
  • 免抵税额和免抵退税额一样吗
  • 原材料会计科目
  • mysql集群原理详解
  • sql 行号
  • win10预览版21277
  • ubuntu系统中如何安装WiFi驱动
  • groove音乐怎么添加本地音乐
  • windows开机显示正在清理
  • mac怎么安装安装包
  • linux Intel 845集成显示驱动下载
  • msn无法登录
  • win7系统怎么关闭病毒防护
  • [置顶]津鱼.我爱你
  • win7安装要求配置
  • linux常用shell命令
  • android的intent介绍
  • jquery设置cookie过期时间
  • android 侧滑页面
  • python黑魔法手册
  • jquery中动画效果方法
  • androidsdk的计算机
  • 国家税务总局年底结算
  • 创业板中签钱不能转出吗
  • 微信如何查询个人名下所有银行卡
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设