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

站长之家查询网站丹东建设工程信息网站

站长之家查询网站,丹东建设工程信息网站,seo优化方案报价,淮南建设厅网站目录 一、前言 二、Handler对象 在新启动的子线程发送消息#xff08;源码跟踪#xff09; 三、在主线程中#xff0c;回调 handleMessage 方法的流程是怎样的呢#xff1f; 四、总结说 1、主要由四个部分组成 ①. Message #xff08;主要用于携带消息#xff09;… 目录 一、前言 二、Handler对象 在新启动的子线程发送消息源码跟踪 三、在主线程中回调 handleMessage 方法的流程是怎样的呢 四、总结说 1、主要由四个部分组成 ①. Message 主要用于携带消息 ②. Handler 主要用于发送和处理消息 ​​​​​​​③. MessageQueue 它是一个消息队列 ​​​​​​​④. Looper 它是一个循环器 2、常见用法与源码解读 1、子线程 2、主线程 ​​​​​​​ 系列文章 Handler异步消息传递机制一Handler常用基本用法 Handler异步消息传递机制二在子线程中创建Handler Handler异步消息传递机制三在主线程、子线程中创建Handler源码Android 9.0解析 Handler异步消息传递机制四Handler发送消息流程源码Android 9.0解析 一、前言 上篇文章我们从源码角度分析了如何在主线程、子线程创建Handler对象。详细可参考Handler异步消息传递机制三在主线程、子线程中创建Handler源码Android 9.0彻底解析  那么创建Handler之后如何发送消息呢这个流程相信大家也已经非常熟悉了我们继续以文章 Handler异步消息传递机制一Handler常用实现方式 的demo为例然后进行源码跟踪解析 二、Handler对象 在新启动的子线程发送消息源码跟踪 下面是 Handler对象在新启动的子线程发送消息  的代码 public class DownLoadAppFile {public void download(String urlPath, Handler handler, ProgressBar pb) {try {//下载apk的代码这里用线程睡眠模拟Thread.currentThread().sleep(3*1000);} catch (InterruptedException e) {e.printStackTrace();}Message msg Message.obtain();msg.what 1;//成功//msg.what 2;//失败handler.sendMessage(msg);//发送消息} } Handler 到底是把 Message 发送到哪里去了呢 为什么之后又可以在 Handler 的 handleMessage 方法中重新得到这条Message呢 接下来我们来看一下发送消息的源码 public final boolean sendMessage(Message msg){return sendMessageDelayed(msg, 0);} 它里面调用了sendMessageDelayed方法 往下追踪 public final boolean sendMessageDelayed(Message msg, long delayMillis){if (delayMillis 0) {delayMillis 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() delayMillis);} 我们可以看到 sendMessageDelayed 方法其中 msg 参数就是我们发送的 Message 对象 而 delayMillis 参数则表示延迟发送消息的时间毫秒这里默认传入的为0 往下追踪 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 方法同样接收两个参数其中msg参数就是我们发送的 Message 对象 而 uptimeMillis 参数则表示发送消息的时间SystemClock.uptimeMillis() delayMillis 即它的值等于自系统开机到当前时间的毫秒数再加上延迟时间。 然后对 MessageQueue 对象 queue 进行了赋值这个 MessageQueue 又是什么东西呢 学过java基础的可能会马上想到Queue基本上一个队列就是一个先入先出FIFO的数据结构。 同样在这里 MessageQueue  直译过来就是 消息队列 的意思用于将所有收到的消息以队列的形式进行排列并提供入队和出队的方法。 那么 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;  即msg.target 赋值为 this也就是把当前所在类 Handler作为 msg 的 target 属性。 然后将这三个参数都传递到 MessageQueue 的 enqueueMessage 方法中 也就是说handler发出的消息最终会保存到消息队列中去。 调用 sendMessage 方法其实最后是调用了类 MessageQueueen 消息队列的 enqueueMessage 入队方法。 那么有了 MessageQueue 消息队列的 enqueueMessage 入队方法它必然有相对应的出队方法。 Handler 对象在新启动的子线程发送消息以后接下来在主线程中Handler类处理消息的方法 handleMessage 被自动回调。 三、在主线程中回调 handleMessage 方法的流程是怎样的呢 那么接下来在主线程中回调 handleMessage 方法的流程是怎样的呢 Android的主线程就是 ActivityThread主线程的入口方法为main我们继续来看一下 ActivityThread 类中main方法的源代码 public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ActivityThreadMain);// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0(pre-initialized);Looper.prepareMainLooper();// Find the value for {link #PROC_START_SEQ_IDENT} if provided on the command line.// It will be in the format seq114long startSeq 0;if (args ! null) {for (int i args.length - 1; i 0; --i) {if (args[i] ! null args[i].startsWith(PROC_START_SEQ_IDENT)) {startSeq Long.parseLong(args[i].substring(PROC_START_SEQ_IDENT.length()));}}}ActivityThread thread new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler null) {sMainThreadHandler thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, ActivityThread));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException(Main thread loop unexpectedly exited);}第47行调用了 Looper.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();// Allow overriding a threshold with a system prop. e.g.// adb shell setprop log.looper.1000.main.slow 1 stop startfinal int thresholdOverride SystemProperties.getInt(log.looper. Process.myUid() . Thread.currentThread().getName() .slow, 0);boolean slowDeliveryDetected false;for (;;) {Message msg queue.next(); // might blockif (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 loggerfinal Printer logging me.mLogging;if (logging ! null) {logging.println( Dispatching to msg.target msg.callback : msg.what);}final long traceTag me.mTraceTag;long slowDispatchThresholdMs me.mSlowDispatchThresholdMs;long slowDeliveryThresholdMs me.mSlowDeliveryThresholdMs;if (thresholdOverride 0) {slowDispatchThresholdMs thresholdOverride;slowDeliveryThresholdMs thresholdOverride;}final boolean logSlowDelivery (slowDeliveryThresholdMs 0) (msg.when 0);final boolean logSlowDispatch (slowDispatchThresholdMs 0);final boolean needStartTime logSlowDelivery || logSlowDispatch;final boolean needEndTime logSlowDispatch;if (traceTag ! 0 Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));}final long dispatchStart needStartTime ? SystemClock.uptimeMillis() : 0;final long dispatchEnd;try {msg.target.dispatchMessage(msg);dispatchEnd needEndTime ? SystemClock.uptimeMillis() : 0;} finally {if (traceTag ! 0) {Trace.traceEnd(traceTag);}}if (logSlowDelivery) {if (slowDeliveryDetected) {if ((dispatchStart - msg.when) 10) {Slog.w(TAG, Drained);slowDeliveryDetected false;}} else {if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, delivery,msg)) {// Once we write a slow delivery log, suppress until the queue drains.slowDeliveryDetected true;}}}if (logSlowDispatch) {showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, dispatch, 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.recycleUnchecked();}} 我们可以看到前面几行代码首先对 Looper、MessageQueue 对象进行了赋值 然后第23行进入了一个死循环for( ; ; ){ }然后不断地调用的 MessageQueue 的 next 方法 Message msg queue.next() 很明显这个 next 方法就是消息队列的出队方法。 接下来你会发现第57行执行了 msg.target.dispatchMessage(msg); 其中 msg.targe t就是指的 Handler 对象你回看一下上面enqueueMessage()方法就可以看出来。 接下来当然就要看一看 Handler 中 dispatchMessage 方法的源码了如下 /*** Handle system messages here.*/public void dispatchMessage(Message msg) {if (msg.callback ! null) {handleCallback(msg);} else {if (mCallback ! null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}} 在第8行进行判断如果 mCallback 不为空则调用 mCallback 的 handleMessage 方法 否则直接调用Handler的handleMessage方法并将消息对象作为参数传递过去。 这样我相信大家就都明白了为什么 handleMessage 方法中可以获取到之前发送的消息了吧 四、总结说 1、主要由四个部分组成 ①. Message 主要用于携带消息 在线程之间传递可在内部携带少量信息用于不同线程之间交换数据 可以使用what、arg1、arg2字段携带整型数据 obj字段携带Object对象 ​​​​​​​②. Handler 主要用于发送和处理消息 1、如果看过Handler源码你会知道 Handler 构造器 做了 Looper 对象是否为空的判定 也就是创建Handler对象之前必须拥有不为null的Looper对象。 所以子线程创建Handler后会报错它需要调用 prepare()方法。 2、我们平时可以直接在主线程中使用Handler 那是因为在应用程序启动时在入口的main方法中已经默认为我们创建好了Looper。 主线程中内部调用了Looper的prepareMainLooper方法 而prepareMainLooper方法里面调用了Looper的prepare() 方法所以不会报错。 3、sendMessage方法用来发送消息最终会回到handleMessage方法进行处理。 ​​​​​​​③. MessageQueue 它是一个消息队列 1、先入先出FIFO的数据结构。 主要存放所有通过Handler发送的消息 它们会一直存在于队列中等待被处理 2、每个线程只有一个MessageQueue。 enqueueMessage 入队方法next 出队方法 ​​​​​​​④. Looper 它是一个循环器 调用loop方法后会不断从MessageQueue 取出待处理的消息 然后传递到handleMessage进行处理 2、常见用法与源码解读 1、子线程 Handler对象调用 sendMessage 等方法发送消息源码内部在调用过程中得到 MessageQueue 对象它是先入先出的队列 其实最后是调用MessageQueue 消息队列的 enqueueMessage 入队方法收到的消息以队列的形式进行排列 2、主线程 Android 的主线程就是 ActivityThread主线程的入口为main方法main方法内部 1Looper 调用 prepareMainLooper 静态方法内部会去调用 prepare 方法创建 一个Looper对象 方法内部具体 判读是否有Looper对象 有提示 “每个线程只能创建一个 Looper对象”没有创建一个新的Looper设置进去 2Looper调用 loop 方法loop方法内部 首先调用 myLooper 方法去取一个Looper对象 如果Looper对象为空会抛出一个异常提示没有Looper对象 如果Looper不为空继续执行得到 MessageQueueen 消息队列然后进行 for循环操作 for循环里面是 MessageQueueen 对象调用 next 出队方法得到一个个Message 消息调用dispatchMessage发送消息 最后通过回调 handleMessage 方法并把 Message 消息依次传递过去。 这里采用网上的一张图个人感觉图片概括得很好就没必要再去造同样的轮子了在新窗口打开可浏览大图 不错博文可参考 Android异步消息处理机制完全解析带你从源码的角度彻底理解_郭霖的专栏-CSDN博客_android 异步消息 Android进阶——Android消息机制之Looper、Handler、MessageQueen_点击置顶文章查看博客目录全站式导航-CSDN博客_handler looper
http://www.dnsts.com.cn/news/254283.html

相关文章:

  • 泰兴网站建设jpress 和wordpress
  • 受欢迎的聊城网站建设网站建设预付费入什么科目
  • 门户网站建设标准建网站电脑版和手机版怎么做
  • 景德镇网站制作网站设计步骤图
  • 内网建设网站外网访问网站设计_网站建设_手机网站建设
  • 沈阳网站建设聚艺科技万网域名查询ip
  • 丹徒网站建设服务企业vi设计主要包括哪些内容
  • 网站文章突然不收录展示形网站怎么建
  • 能源科技网站建设网络系统软件应用与维护
  • 无锡企业免费建站网站开发美工绩效考核
  • 汕头市网站建设分站服务机构鞍山信息港二手房
  • 台州国强建设网站安阳免费搭建自己的网站
  • 小网站asp好还是php好wordpress 修改配置
  • 如何用xampp做网站手机app开发网站模板下载
  • 怎样在微信上做网站中山网站建设文化策划书
  • 一个网站怎么做聚合wordpress 导入
  • 如何给wordpress添加一张网站背景汕头企业网站推广方法
  • 新乡中企网站建设网站开发软件要求
  • 松原做公司网站营销qq多少钱一个月
  • 英文网站营销WordPress模仿教程
  • 戚墅堰做网站个人网页设计模板网站
  • 开发网站需要什么语言珠海市网站开发公司
  • 汕尾网站建设公司网站设计公司杭州
  • 不注册公司可以做网站吗秦皇岛的网站建设公司
  • wordpress360网站卫士青岛经济师考试
  • 网站建设与管理工资家具设计师要学哪些软件
  • 东莞网站系统找哪里jsp网站建设美食
  • 国土资源局加强网站建设吉林长春seo网络推广
  • 做网站一般需要哪些文件夹阿坝县建设局网站
  • 高端公司网站建设网站推广有哪些方法