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

网站建设技术标书canva 可画主页首页首页模板素材

网站建设技术标书,canva 可画主页首页首页模板素材,网站 数据库 模板,品牌策划 品牌年度服务本文是从源码的角度对andorid异步消息处理机制的梳理#xff0c;那么在文章开始阶段#xff0c;先简单介绍#xff0c;异步消息处理机制中各部件的作用以及处理处理机制的概述 1、Handler、Message、MessageQueue、Looper功能简述 Handler负责消息处理#xff0c;包括消息…本文是从源码的角度对andorid异步消息处理机制的梳理那么在文章开始阶段先简单介绍异步消息处理机制中各部件的作用以及处理处理机制的概述 1、Handler、Message、MessageQueue、Looper功能简述 Handler负责消息处理包括消息的发送和消息的接收内部跟Looper有关联。 Message是消息的载体里面封装了消息的具体内容 MessageQueue是消息列表存在着由Handler发送的Message注意MessageQueue内部是链表实现并不是队列 Looper会创建一个死循环负责从MessageQueue中循环取出Message 2、异步消息处理机制简述 android通过Handler发送异步消息Message放入MessageQueue消息列表中在Handler内部有一个LooperLooper的实现是一个死循环负责从MessageQueue中取出Message并将Message传递回给Handler最后Handler负责处理对应message。 3、andorid为什么要使用异步消息处理机制 主要用于处理多线程更新ui的并发问题。若没有异步消息处理机制此时多个线程在不加同步锁的情况下去更新ui界面那很可能会造成ui页面的显示的错乱。 接下来从源码的角度剖析Handler、Message、MessageQueue、Looper的具体实现 Handler Handler构造方法如下 public Handler(Callback callback, boolean async) {......mLooper Looper.myLooper();if (mLooper null) {throw new RuntimeException(Cant create handler inside thread that has not called Looper.prepare());} mQueue mLooper.mQueue; ...... } 实例化Handler同时通过调用Looper的myLooper()方法一并初始化了Looper对象当Looper对象为空时会抛出一个异常那么myLooper()方法获取的对象何时为空 static final ThreadLocalLooper sThreadLocal new ThreadLocalLooper(); public static Looper myLooper() {return sThreadLocal.get(); }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)); } 可以看出Looper对象是从sThreadLocal变量中获取而sThreadLocal又是在Looper调用prepare()方法后设置的同时在设置之前会判断是否已存在Looper对象若存在直接抛出异常这表明一个Handler只能包含一个Looper 一般实例化一个Handler对象后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 sendMessageDelayed(Message msg, long delayMillis){ if (delayMillis 0) { delayMillis 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() delayMillis); } 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); } 其实最终调用到的就一个方法sendMessageAtTime()方法而sendMessageAtTime()方法就是直接调用了enqueueMessage()方法 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); } 这里的this指的是当前Handler对象queue调用enqueueMessage()方法将Handler发送出去的Message对象放入queue中 此时已经将消息存入MessageQueue中了那么下一步就是Looper去取MessageQueue中的Message并传递给Handler Looper 前面已经介绍Looper的初始化是在Handler的构造方法中进行的在做完这些准备工作后Looper就会开启循环去获取MessageQueue中的Message执行的方法是loop()方法 public static void loop() { final Looper me myLooper(); if (me null) { throw new RuntimeException(No Looper; Looper.prepare() wasnt 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); if (logging ! null) { logging.println( Finished to msg.target msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasnt corrupted. final long newIdent Binder.clearCallingIdentity(); if (ident ! newIdent) { Log.wtf(TAG, Thread identity changed from 0x Long.toHexString(ident) to 0x Long.toHexString(newIdent) while dispatching to msg.target.getClass().getName() msg.callback what msg.what); } msg.recycle(); } } 可以看到在第13行代码程序进入一个死循环然后获取到一个非空的Message对象后Handler会调用dispatchMessage()方法 public void dispatchMessage(Message msg) {//第一种处理消息方式if (msg.callback ! null) {handleCallback(msg);} else {if (mCallback ! null) {//第二种处理消息方式if (mCallback.handleMessage(msg)) {return;}}//第三种处理消息方式handleMessage(msg);} } 根据源码可以看出Handler一共有三种处理消息的方式那让我们来分析一下都是哪些情况会执行对应的处理方式 其实handler发送消息的方式分两大系列第一类是send系列第二类是post系列。 send系列 Message msg mHandler.obtainMessage(); //发送一个消息码为0的空消息 mHandler.sendEmptyMessage(0); //发送一个消息码为0绝对时间点为1000ms的空消息该时间应该大于等于当前时间下同 mHandler.sendEmptyMessageAtTime(0, 1000); //发送一个消息码为0延时时间为1000ms的空消息 mHandler.sendEmptyMessageDelayed(0, 1000); //发送一个没有延时的msg封装的消息 mHandler.sendMessage(msg); //发送一个绝对时间点为1000ms的msg封装的消息 mHandler.sendMessageAtTime(msg, 1000); //发送一个延时时间为1000ms的msg封装的消息 mHandler.sendMessageDelayed(msg, 1000); //立即发送一个msg封装的消息到消息队列的最前端 mHandler.sendMessageAtFrontOfQueue(msg); 分析源码可知除了最后一中调用其余所有send系列的方法最终都是调用sendMessageAtTime()方法。 而此时Handler对应的dispatchMessage()方法所执行到的是第二种处理消息方式和第三种处理消息方式主要看实现的Handler类的构造方法中有没有传入CallBack对象 private Handler mHandler new Handler() {Overridepublic void handleMessage(Message msg) {//接收消息之后处理消息} }; 以上的形式Handler对应的dispatchMessage()会调用第三种处理消息方式 private Handler handler1 new Handler(new Handler.Callback() {Overridepublic boolean handleMessage(Message msg) {//接收消息之后处理消息return true;} }); 以上的形式Handler对应的dispatchMessage()会调用第二种处理消息方式值得注意的是CallBack接口对象的handleMessage()方法带有一个boolean的返回值若返回false此方法执行完后消息会继续传递到第三种处理消息方法中去所以如果没有特殊的要求此方法一般返回true。 post系列 mHandler new Handler();mHandler.post(new Runnable() {Overridepublic void run() {}});mHandler.postAtTime(new Runnable() {Overridepublic void run() {} }, new Object(), 1000);mHandler.postDelayed(new Runnable() {Overridepublic void run() {} }, 1000);mHandler.postAtFrontOfQueue(new Runnable() {Overridepublic void run() {} }); 此处Handler不是发送Message对象而是发送一个Runnable接口那么Handler不是发送Message对象的吗这里怎么发生Runnable接口其实最终发送的还是Message对象只是在后续的进行了转换 public final boolean postAtTime(Runnable r, Object token, long uptimeMillis){return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } post系列方法最终都会调用到PostAtTime()方法内部依旧是调用了sendMessageAtTime()方法只是通过调用getPostMessage方法对Runnable接口进行了转换。 private static Message getPostMessage(Runnable r, Object token) {Message m Message.obtain();m.obj token;m.callback r;return m; } Message对象的callback变量赋值为传入的Runnable接口那么由此可以看出以post系列的所有方法所传入的消息最终都会执行Handler中dispatchMessage()方法中的第一种处理消息方式。 Message Message对象的创建一般采用Message的obtain()方法或者obtainMessage()方法而不是以Message message new Message()形式进行这是官方文档所建议的。主要原因是因为Message内部维护了一个消息池执行obtain()方法或者obtainMessage()方法便是从消息池中获取实例从而避免实例化带来的内存浪费。 /** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() {synchronized (sPoolSync) {if (sPool ! null) {Message m sPool;sPool m.next;m.next null;m.flags 0; // clear in-use flagsPoolSize--;return m;}}return new Message(); } Handler使用不当造成内存泄漏 内存泄漏的定义是对象持有比自己生命周期长的对象引用导致自身无法被垃圾回收器回收。 那么在handler的使用过程中什么时候会造成内存泄漏举个例子当你开启Thread请求异步数据发出请求后你退出当前activity而异步数据在你退出activity页面后才返回此时activity对象将永远持有handler对象导致无法被回收造成内存泄漏。解决方法 //从消息队列中移出post系列方法中Runnable对象的消息 mHandler.removeCallbacks(Runnable r); //从消息队列中移除消息码为“what”的消息 mHandler.removeMessages(int what); 可以在activity的onDestory()中调用以上方法移除未执行完毕的异步请求清除消息队列中对应的消息。
http://www.dnsts.com.cn/news/76549.html

相关文章:

  • 基于asp.net网站开发中华室内设计协会
  • 网站策划编辑信阳做网站的公司
  • 长沙 外贸网站建设公司WordPress添加下一篇
  • 网站如何建设目录结构网站建设与管理课程设计论文
  • 和韩国做贸易的网站微信小程序注册流程
  • wordpress设置后台信息搜索引擎优化要考虑哪些方面
  • seo网站编辑是做什么的建筑人才网官
  • 机械东莞网站建设0769网站的支付系统怎么做的
  • 网站优化 月付费安阳哪里有做网站的
  • 莒县网站建设沈阳做招聘网站
  • 北京网站制作到诺然搜索引擎优化营销
  • 无锡个人网站建设手机如何建立网站步骤
  • 网站结构布局重庆网站建设哪家公司哪家好
  • 与众不同的网站网站建设客户分析调查问卷
  • 网站配色方案网络传媒网站
  • 企业型网站建设哪家比较好找人做网站需求怎么写
  • 提示网站有风险什么是营销型网站?
  • 中科建建设发展有限公司网站深圳网站建设的价格
  • 徐州市中宇建设工程有限公司网站专业网站美工
  • 成都房地产网站建设吉林大学学院网站建设群
  • 门户网站建设的公司网站建设开发费怎么做账
  • 手机网站开发 1433端口错误美化wordpress
  • 微信的网站怎么做的永久云服务器购买
  • 义乌网站设计制作价格如何安装wordpress
  • 中国水电建设集团网站安徽省建设厅查询网站
  • 集团公司网站方案外贸网页制作公司
  • 用eclipse编程做网站黄江网站建设
  • 公司要我做网站_没有公司的材料是不是不可以做怎么找运营团队
  • 人员调动在网站上怎么做门户网站建设方案内容
  • 网站建设数据收集方法接外贸单的平台有哪些