花样使用Handler与源码分析

接下来我将详细讲解“花样使用Handler与源码分析”的完整攻略。

概述

在Android应用程序中使用Handler,可以让UI线程和工作线程之间进行消息传递,从而实现UI更新。Handler是实现线程间通信的强大的工具,熟练使用Handler可以很好地提高Android应用程序的响应性和性能。

本文将介绍使用Handler的基本原则和使用技巧,并解析Handler的源码,帮助开发者更好地掌握Handler的使用。

Handler的基本原则

  1. Handler的创建必须在主线程中进行。

  2. 每个Handler实例关联一个Looper和MessageQueue。

  3. Handler可以将Runnable或Message对象投递到MessageQueue中。

  4. 通过Handler.post或Handler.sendMessage方法可以向MessageQueue中投递Runnable或Message对象。

  5. 当Handler处理消息时,它会与当前的线程进行关联。

  6. Handler可以用于实现定时器功能。

  7. Handler不建议用作数据存储容器。建议使用其他合适的数据存储方式。

Handler的使用技巧

以下是使用Handler的一些技巧。

把Handler放在子线程中

Handler通常与主线程关联,但也可以与其他线程关联。在UI线程中使用Handler可以更新UI,但是在子线程中使用Handler也可以执行一些耗时操作,从而避免阻塞UI线程。下面是使用Handler在子线程中执行的示例。

val handler = Handler(Looper.getMainLooper())

Thread(Runnable {
    // 一些耗时的操作
    val message = handler.obtainMessage(1, "result")
    handler.sendMessage(message)
}).start()

val handlerCallback = object : Handler.Callback {
    override fun handleMessage(msg: Message): Boolean {
        // 处理消息
        return true
    }
}

val handler = Handler(Looper.getMainLooper(), handlerCallback)

Thread(Runnable {
    // 一些耗时的操作
    val message = Message.obtain()
    message.what = 1
    message.obj = "result"
    handler.sendMessage(message)
}).start()

使用Handler实现UI更新

在Android应用程序中经常需要在子线程中进行耗时操作,并在操作完成后更新UI。为了实现UI更新,我们需要使用Handler。下面是使用Handler在子线程中更新UI的示例。

val handler = Handler(Looper.getMainLooper())

Thread(Runnable {
    // 在子线程中执行耗时操作
    val message = handler.obtainMessage()
    message.what = 1
    message.obj = "result"
    handler.sendMessage(message)
}).start()

val handlerCallback = object : Handler.Callback {
    override fun handleMessage(msg: Message): Boolean {
        when (msg.what) {
            1 -> {
                // 更新UI
                textView.text = msg.obj.toString()
            }
        }
        return true
    }
}

val handler = Handler(Looper.getMainLooper(), handlerCallback)

Thread(Runnable {
    // 在子线程中执行耗时操作
    val message = Message.obtain()
    message.what = 1
    message.obj = "result"
    handler.sendMessage(message)
}).start()

Handler源码分析

本节将对Handler的源码进行分析。

Handler的构造函数

Handler的构造函数中关联了Looper和MessageQueue。Handler通过Looper.getMainLooper()方法获取UI线程的Looper,这使得Handler与UI线程关联。而MessageQueue是由Looper创建的,每个Handler实例的Message对象都是存储在该MessageQueue中的。

class Handler(looper: Looper = Looper.myLooper() !!
): Object(), Callback {
    private var mLooper = looper
    private var mQueue: MessageQueue = looper.mQueue
}

Handler.post方法的实现

Handler.post方法用来将Runnable对象放入MessageQueue中,以便在未来某个时刻运行该Runnable。当Handler.post方法调用时,它会创建一个新的Message对象,然后将该Message对象发送到当前Handler关联的MessageQueue中。

fun post(r: Runnable): Boolean {
    return sendMessageDelayed(getPostMessage(r), 0)
}

fun sendMessageDelayed(msg: Message, delayMillis: Long): Boolean {
    if (delayMillis < 0) {
        delayMillis = 0
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)
}

fun sendMessageAtTime(msg: Message, uptimeMillis: Long): Boolean {
    val queue: MessageQueue = mQueue
    if (queue == null) {
        throw IllegalStateException("Handler not attached")
    }
    return enqueueMessage(queue, msg, uptimeMillis)
}

private fun enqueueMessage(queue: MessageQueue, msg: Message, uptimeMillis: Long): Boolean {
    msg.target = this
    return queue.enqueueMessage(msg, uptimeMillis)
}

Handler.sendMessage方法的实现

Handler.sendMessage方法用来将Message对象放入MessageQueue中,以便在未来某个时刻运行该对象。当Handler.sendMessage方法调用时,它会创建一个新的Message对象,然后将该Message对象发送到当前Handler关联的MessageQueue中。

fun sendMessage(msg: Message): Boolean {
    return sendMessageDelayed(msg, 0)
}

fun sendMessageDelayed(msg: Message, delayMillis: Long): Boolean {
    if (delayMillis < 0) {
        delayMillis = 0
    }
    val uptimeMillis: Long = SystemClock.uptimeMillis() + delayMillis
    return sendMessageAtTime(msg, uptimeMillis)
}

fun sendMessageAtTime(msg: Message, uptimeMillis: Long): Boolean {
    val queue: MessageQueue = mQueue
    if (queue == null) {
        throw IllegalStateException("Handler not attached")
    }
    return enqueueMessage(queue, msg, uptimeMillis)
}

private fun enqueueMessage(queue: MessageQueue, msg: Message, uptimeMillis: Long): Boolean {
    msg.target = this
    return queue.enqueueMessage(msg, uptimeMillis)
}

Handler.handleMessage方法的实现

Handler.handleMessage方法是一个抽象方法。当有消息需要处理时,Handler会调用该方法。子类需要重写该方法,以根据不同的消息类型执行不同的操作。对于不同的消息类型,Handler会执行不同的操作。是最终实现逻辑,前面的方法都是为它服务。

open fun handleMessage(msg: Message) {
}

以上就是本文的“花样使用Handler与源码分析”的完整攻略,希望对您的学习有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:花样使用Handler与源码分析 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 详解JS浏览器事件模型

    详解JS浏览器事件模型 JS浏览器事件模型是指浏览器中的事件处理机制,它允许开发者在网页中添加交互性和动态性。本文将详细讲解JS浏览器事件模型,包括事件类型、事件处理程序、事件流、事件委托等内容,并提供两个示例说明。 事件类型 在JS浏览器事件模型中,事件类型是指用户或浏览器执行的操作,如单击、双击、鼠标移动、键盘按键等。以下是一些常见的事件类型: 鼠标事件…

    云计算 2023年5月16日
    00
  • openstack (共享服务) 消息队列rabbitmq服务 云计算openstack共享组件——消息队列rabbitmq(3)

      一、MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。队列的…

    云计算 2023年4月10日
    00
  • 腾讯推出国内首个云原生成本优化开源项目 Crane

    关于我们 更多关于云原生的案例和知识,可关注同名【腾讯云原生】公众号~ 福利: ①公众号后台回复【手册】,可获得《腾讯云原生路线图手册》&《腾讯云原生最佳实践》~ ②公众号后台回复【系列】,可获得《15个系列100+篇超实用云原生原创干货合集》,包含Kubernetes 降本增效、K8s 性能优化实践、最佳实践等系列。 ③公众号后台回复【白皮书】,可…

    云计算 2023年4月11日
    00
  • 利用.net core实现反向代理中间件的方法

    利用.NET Core实现反向代理中间件的方法 反向代理是一种常见的Web应用程序架构,它可以将客户端请求转发到后端服务器。在.NET Core中,我们可以使用反向代理中间件来实现反向代理。本文将提供一个完整的攻略,包括如何使用.NET Core实现反向代理中间件。以下是详细步骤: 步骤1:创建.NET Core Web应用程序 在实现反向代理中间件之前,我…

    云计算 2023年5月16日
    00
  • ASP.NET(C#) Web Api通过文件流下载文件的实例

    下面是“ASP.NET(C#) Web Api通过文件流下载文件的实例”的完整攻略: 1. 创建ASP.NET Web API应用程序 首先,我们需要在Visual Studio中创建一个ASP.NET Web API应用程序。具体步骤如下: 打开Visual Studio,点击“新建项目”。 选择“ASP.NET Web应用程序”,并命名新项目。 在“新建…

    云计算 2023年5月17日
    00
  • python进行相关性分析并绘制散点图详解

    Python进行相关性分析并绘制散点图详解 引言 批量数据分析是现代数据科学领域中非常重要的一部分,相关性分析是其中一个常用的统计分析方法。Python是一种十分流行的数据分析工具,它提供了很多用于数据分析和可视化的库和工具,通过使用Python,我们可以很方便的进行相关性分析并绘制散点图,这使得数据科学家们可以更好地识别和分析数据。 数据准备 在进行相关性…

    云计算 2023年5月18日
    00
  • asp.net基于JWT的web api身份验证及跨域调用实践

    ASP.NET基于JWT的Web API身份验证及跨域调用实践 本文将详细讲解 ASP.NET 基于 JWT 的 Web API 身份验证及跨域调用实践,帮助读者理解如何构建一个基于 JWT 的 API 并使用跨域调用这个 API。 什么是JWT JWT (JSON Web Token)是一个开放标准(RFC 7519),用于在各方之间安全地传输信息。它可以…

    云计算 2023年5月17日
    00
  • C#使用有道ip地址查询接口方法实例详解

    C#使用有道ip地址查询接口方法实例详解 本文将介绍如何在C#中使用有道ip地址查询接口进行IP地址查询。我们将会学习: 如何发送HTTP请求调用有道API 如何将API返回的JSON数据解析成C#对象 发送HTTP请求调用有道API 有道IP地址查询API是通过GET方法访问,请求URL为: http://apis.youdao.com/iplocatio…

    云计算 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部