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

机械技术支持东莞网站建设wordpress如何进入

机械技术支持东莞网站建设,wordpress如何进入,淘宝关键词推广,网站设计案例网站Handler 的主要使用场景 子线程完成耗时操作的过程中#xff0c;通过 Handler 向主线程发送消息 Message#xff0c;用来更新 UI 界面。因为 Android 是在主线程中更新 UI 的#xff0c;在主线程出现耗时操作时#xff0c;就会导致用户界面卡顿#xff0c;所以我们一般都…Handler 的主要使用场景 子线程完成耗时操作的过程中通过 Handler 向主线程发送消息 Message用来更新 UI 界面。因为 Android 是在主线程中更新 UI 的在主线程出现耗时操作时就会导致用户界面卡顿所以我们一般都把耗时的操作网络请求、IO 等放到子线程中然后通过 Handler 的方式让主线程更新 UI。 new Handler() 如果是无参构造器其中调用了重载的构造方法并分别传入 null 与 false。并在构造方法中给两个全局变量赋值两者都是通过 Looper 来获取。 UnsupportedAppUsage final Looper mLooper; final MessageQueue mQueue; UnsupportedAppUsage final Callback mCallback; final boolean mAsynchronous;public Handler(Nullable Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class? extends Handler klass getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) (klass.getModifiers() Modifier.STATIC) 0) { Log.w(TAG, The following Handler class should be static or leaks might occur: klass.getCanonicalName()); } } mLooper Looper.myLooper(); if (mLooper null) { throw new RuntimeException( Cant create handler inside thread Thread.currentThread() that has not called Looper.prepare()); } mQueue mLooper.mQueue; mCallback callback; mAsynchronous async; }Looper 启动一个 Java 的入口函数是 main 方法当 main 函数执行完毕后程序就会停止运行但是我们打开一个 Activity只要不返回则会一直显示即 Activity 所在进程会一直处于运行状态。 实际上 Looper 内部维护一个无限循环保证 APP 的持续运行。 Activity 启动时ActivityThread#main 方法是新 APP 进程的入口 // ActivityThread#main public static void main(String[] args) {//...// 初始化当前进程的 Looper 对象Looper.prepareMainLooper();//...if (sMainThreadHandler null) { sMainThreadHandler thread.getHandler(); }//...// 调用 Looper#loop 方法开启无限循环Looper.loop();//... } // Looper#prepareMainLooper public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper ! null) { throw new IllegalStateException(The main Looper has already been prepared.); } // 将从线程本地变量中取出的 Looper 对象赋值给 sMainLooper 对象sMainLooper myLooper(); } }// Looper#prepare private static void prepare(boolean quitAllowed) { // 一个线程中的 Looper#prepare 方法只能执行一次 否则会抛出异常if (sThreadLocal.get() ! null) { throw new RuntimeException(Only one Looper may be created per thread); } // 新建一个 Looper 对象 并设置到线程本地变量中 // 即创建的 Looper 与当前线程绑定sThreadLocal.set(new Looper(quitAllowed)); } // Looper#Looper 构造方法 private Looper(boolean quitAllowed) { // 初始化了 MessageQueue 对象mQueue new MessageQueue(quitAllowed); mThread Thread.currentThread(); }// Looper#myLooper public static Nullable Looper myLooper() { // 从线程本地变量中取出 Looper 对象return sThreadLocal.get(); } Looper#prepare 方法一个线程中只能被调用一次会判定线程本地变量是否为空即 Looper 的构造方法在一个线程中只能被调用一次构造方法中 MessageQueue 在一个线程中只会被初始化一次所以一个线程只会有一个 MessageQueue 对象。 Looper 的任务就是不断从 MessageQueue 中取出 Message然后处理 Message 中指定的任务。在 main 方法中调用的 Looper.loop 方法就是完成这件事的。Looper#loop 方法中有个死循环这就是 Android App 进程能不断运行的原因。 如果从 MessageQueue 中取出的 message 不为空则取出 message 的 target 对象并调用其 dispatchMessage 方法处理 Message 方法本身。这个 target 对象就是 Handler。 // Looper#loop public static void loop() { final Looper me myLooper();//...for (;;) { if (!loopOnce(me, ident, thresholdOverride)) { return; } } }// Looper#loopOnce private static boolean loopOnce(final Looper me, final long ident, final int thresholdOverride) {Message msg me.mQueue.next(); // might blockif (msg null) {return false;}//...try { msg.target.dispatchMessage(msg); if (observer ! null) { observer.messageDispatched(token, msg); } dispatchEnd needEndTime ? SystemClock.uptimeMillis() : 0; } catch (Exception exception) { //...} finally { //... }//...return true; }// Message public final class Message implements Parcelable {//...// target 即传递的 Handler 对象UnsupportedAppUsage /*package*/ Handler target; }// Handler#dispatchMessage public void dispatchMessage(NonNull Message msg) { if (msg.callback ! null) { handleCallback(msg); } else { if (mCallback ! null) { if (mCallback.handleMessage(msg)) { return; } } // 调用 handlerMessage 方法handleMessage(msg); } }// Handler#handlerMessage public void handleMessage(NonNull Message msg) { // 该方法为空// 在创建 Handler 时需要继承并重写该方法 } Handler#sendMessage 方法 Handler 包括几个重载的 sendMessage 方法该方法最后会通过 enqueueMessage 方法将 Message 插入到消息队列 MessageQueue 中。这个消息队列就是我们在 ActivityThread 的 main 方法中通过 Looper 创建的 MessageQueue。 enqueueMessage 方法中将 Handler 自身设置为 target 对象后续 Message 会调用此 Handler 的 dispatchMessage 来处理。MessageQueue 是一个按照 Message 执行时间排序的有序队列在使用 enqueueMessage 方法时会根据 Message 的时间 when 来有序插入 Message 到队列中。 Handler#post 方法 在 Looper#loop 从 MessageQueue 中取出 Message 时会调用 target 的 dispatchMessage 来处理消息。 如果 msg.callback 不为空执行的是 handleCallback(msg) 去处理消息如果 msg.callback 为空会调用 handleMessage(msg) 来处理消息(即我们重写的方法)。 private static void handleCallback(Message message) { message.callback.run(); }handleCallback 会直接执行 Runnable 的 run 方法Runnable 实际上是一个回调接口与线程 Thread 无关。 Looper#loop 方法为什么不会阻塞主线程 Looper#loop 方法实际上是一个死循环但是不会造成 UI 线程阻塞。因为在 MessageQueue 的 next 方法中调用了 native 方法 nativePollOnce当调用该方法时主线程会释放 CPU 资源进入休眠状态直到下一条消息到达或者有事务发生通过 pipe 管道写段写入数据唤醒主线程工作采用 epoll 机制是一种IO多路复用机制可以同时监控多个描述符当某个描述符就绪(读或写就绪)则立刻通知相应程序进行读或写操作本质同步I/O即读写是阻塞的。 所以说主线程大多数时候都是处于休眠状态并不会消耗大量CPU资源。 Handler 可能造成内存泄漏 Handler 的 Message 被存储在 MessageQueue 中有些 Message 不能马上被处理在队列中存在的时间很长排序靠后或者有使用了延时执行 sendMessageDelay 来发送 msg导致 Handler 无法被回收如果 Handler 是非静态的那么 Handler 也会导致引用它的 Activity 与 Service 不能被回收。 可能场景是发送一条延时 msg 至 MessageQueue 中未执行就 finish 关闭 Activity。导致 handler 与 Activity 内存都不会被释放。 解决方式是使用一个静态的 Handler 内部类继承 handler且 Handler 持有的对象使用弱引用并且在 Activity 的 onDestroy 方法中移除传入到 MessageQueue 中的消息。 Handler 特性 一个线程只有一个 Looper可以有多个 Handler 来处理消息Looper 通过 Handler 对象的 handlerMessage 方法来处理消息。在两个都不是主线程的线程中想要使用 Handler 的话需要在处理逻辑的线程中创建 Looper有了 Looper 后才能创建 Handler之后再另外的线程中使用 Looper 线程的 handler 对象来发送 message。主线程获得 Looper 方法是Looper.getMainprepare()可以在子线程直接 new 一个 Handler需要在一个线程先 Looper.prepare() 和 Looper.loop()Handler 在创建时会采用当前线程的 Looper 来构造消息循环系统 Looper 在哪个线程创建就和哪个线程绑定Handler 是在其关联的 Looper 对应的线程中处理消息的。 如何验证 Handler 是否持有了外部类的引用 通过 class 判断。 子线程中更新 UI 的方法 首先需要在主线程当中创建一个 Handler 对象并重写 handleMessage() 方法。 然后当子线程中需要进行UI操作时就创建一个 Message 对象并通过 Handler 将这条消息发送出去。 之后这条消息会被添加到 MessageQueue 的队列中等待被处理而 Looper 则会一直尝试从 MessageQueue 中取出待处理消息最后分发回 Handler 的 handleMessage() 方法中。 由于 Handler 的构造函数中我们传入了 Looper.getMainLooper()所以此时 handleMessage() 方法中的代码也会在主线程中运行然后便可以在此更新 UI。 一条Message经过以上流程的辗转调用后也就从子线程进入了主线程从不能更新UI变成了可以更新UI。 总结 应用启动是从 ActivityThread#main 方法开始的先执行了 Looper#prepare 方法创建 Looper 对象并绑定到当前线程 MainThread 中而 Looper 对象创建时会初始化 MessageQueue 队列因此我们会在主线程中获得一个 Looper 对象与 MessageQueue 队列。 当我们创建一个 Handler 子对象时在构造方法中通过 ThreadLocal 方式获取绑定的 Looper 对象并获取此 Looper 对象的成员变量 MessageQueue 作为该 Handler 对象的成员变量。 在子线程中调用创建好的 Handler 子类对象的 sendMessage 方法将 Message 对象的 target 属性设置为 Handler 子对象自身调用 MessageQueue 对象的 enqueueMessage 方法将 msg 插入 MessageQueue 中。 在主线程中的 Looper#loop 方法中会不断读取 MessageQueue 中的消息如果消息不为空就会执行 msg#target#dispatchMessage 方法这个方法会调用我们在创建 Handler 对象时重写的 handlerMessage 方法。
http://www.pierceye.com/news/851083/

相关文章:

  • 微网站制作网站开发创建自己网站的步骤
  • 人才网网站开发手册外链发布平台大全
  • 福州网站备案wordpress打开媒体链接设置
  • 大学网站建设考核办法永春网站设计
  • 哪个设计网站赚钱百度地图网页版进入
  • 网站备案号不存在100m的网站 数据库
  • 网站空间管理平台网站模版 优帮云
  • 网站开发的比较备案期间 需要关闭网站吗
  • 做网站 怎么推广上海市企业服务云十问十答
  • 怎么做一种网站为别人宣传wordpress query_posts()
  • 网站的运营和维护专业做网站官网
  • 详细论述制作网站的步骤做网站需求 后期方便优化
  • 蒙icp备 网站建设学校网站建设管理
  • 做免费外贸网站册域名网站大全免黄
  • 祈网网站建设制作网站如何赚钱
  • 最讨厌网站门户类网站的主页设计
  • 国家建设环保局网站网站做的好赚钱吗
  • 如何设置网站服务器做标签的网站
  • 网站建设高端培训学校做网站交易平台
  • 公司网站建设收费优化网站排名解析推广
  • 昆明快速建站模板汽车网站建设多少钱
  • 网站注销主体注销广州联享网站建设公司怎么样
  • 中山seo建站新手建站教程报价单
  • 台州制作网站软件陈坤做直播在哪个网站
  • 北湖区网站建设公司企业主题wordpress 含演示数据
  • 网站建设简历自我评价做招聘信息的网站有哪些内容
  • 怎么和其它网站做友情链接网络营销师证怎么考
  • 百度推广要自己做网站吗做的视频传到哪个网站好
  • 个人建设门户网站 如何备案网站推广服务报价表
  • 广州企业网站建设哪家服务好西安家政公司网站建设