位置: 编程技术 - 正文

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

  • 增值税开票软件在哪下载
  • 计提维保费
  • 差额征税的税率怎么计算
  • 付款申请单是原单据吗
  • 食品发票可以报销餐费吗
  • 社保基数申报怎么看是否成功
  • 计提 增值税
  • ATM可以存款到对公账户吗?
  • 出售本月转入处置的固定资产应交税费
  • 企业的成本核算包括
  • 进口环节增值税是中央税还是地方税
  • 银行的划分标准
  • 商业折扣的纳税影响
  • 营改增前未完工的老项目可以开专票吗
  • 其他货币资金包括的内容有
  • 工业总产值怎么计算公式
  • 周转材料低值易耗品摊销
  • 经纪人佣金计入什么科目
  • 租赁公司运输费计入什么科目
  • 认缴制下股权转让如何不交税
  • 企业收取的押金要开票吗
  • 发票上传多久可以验旧
  • 所得税汇算清缴表在哪里打印
  • 公司去大厅交社保要带什么证件
  • 城市建设维护税是什么意思
  • 税收分类编码里的劳务是劳务派遣的意思吗
  • 企业外币交易会计核算方法
  • 联营扣点怎么核算保本费用
  • 定额发票2019年规定
  • 种子销售公司
  • 固定资产审计目标
  • 重置申报清册之前的税需要重新申报吗
  • 企业已确认销售收入的售出商品发生销售折让,且不属于
  • 车辆哪些费用计税
  • 出差的住宿费较高的原因
  • win10开机重启陷入死循环
  • 惠普2600打印机故障排除
  • 个人应纳税所得额是要交钱吗
  • 布拉索夫地图
  • 事业单位以固定薪资为准
  • 医疗知识科普图片
  • 治疗孩子咳嗽小秘方,超实用
  • adan算法
  • 命令行mkdir创建文件夹
  • php身份证号码验证
  • cmd more命令
  • 研发企业所得税税率
  • 企业生产过程中执行标准要把握好以下原则
  • 计提固定资产折旧账务处理
  • 财务专用章是干嘛用的
  • 按揭房办理抵押贷款
  • 未抵扣机动车专票红字发票怎么填开
  • 汇算清缴预缴
  • 工程物资是
  • 扶贫差旅费
  • 长期待摊费用怎么记账
  • SQL Server中通配符的使用示例
  • win8系统蓝屏后无法修复
  • 获取linux系统版本
  • centos怎么添加用户
  • imac如何删除客人用户
  • win10如何配置
  • windows10mode
  • 虚拟机安装win7一直卡在完成安装
  • win7无法删除d盘
  • Win10红石版Edge浏览器新扩展功能:关灯(附扩展程序使用)
  • Win10 Mobile RS1预览版14267.1004升级过程截图
  • 拉伸设置
  • qt pro load
  • 安卓核心架构
  • activitythread main方法
  • shell脚本编写步骤
  • .nodejs
  • 安卓基础入门教程
  • python remote
  • 手机关卡类游戏
  • android获取手机的基本信息
  • javascript的dom操作
  • python遍历文件目录
  • 北京重点税源直报平台登录
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设