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

Android7 Input(六)InputChannel

概述:

本文讲述Android Input输入框架中 InputChannel的功能。从前面的讲述,我们知道input系统服务最终将输入事件写入了InputChannel,而input属于system_server进程,App属于另外一个进程,当Input系统服务想要把事件传递给App进行处理时这里就涉及到了一个跨进程通信的问题。Android系统中常用的就是通过Binder实现进程间通信,但是Binder属于CS架构,单一的连接不能实现Client和Server的双向通信,如果我们想要实现进程间的双向通信,则必须建立两个Binder通道。Android系统有多个App 这样则每个App都需要两个Binder通信通道才能完成Input系统进行通信。这显然不是很好的选择, 所以Android系统的Input框架选择了传统Linux的Unix域通信机制,也就是我们本章讲述的InputChannel实现原理。

本文涉及的源码路径

frameworks/native/libs/input/InputTransport.cpp

frameworks/base/core/java/android/view/InputChannel.java

frameworks/base/core/jni/android_view_InputChannel.cpp

InputChannel类

public final class InputChannel implements Parcelable {private static final String TAG = "InputChannel";......@SuppressWarnings("unused")private long mPtr; // used by native codeprivate static native InputChannel[] nativeOpenInputChannelPair(String name);    private native void nativeDispose(boolean finalized);private native void nativeTransferTo(InputChannel other);private native void nativeReadFromParcel(Parcel parcel);private native void nativeWriteToParcel(Parcel parcel);private native void nativeDup(InputChannel target);private native String nativeGetName();......public InputChannel() {}@Overrideprotected void finalize() throws Throwable {try {nativeDispose(true);} finally {super.finalize();}}......public static InputChannel[] openInputChannelPair(String name) {if (name == null) {throw new IllegalArgumentException("name must not be null");}if (DEBUG) {Slog.d(TAG, "Opening input channel pair '" + name + "'");}return nativeOpenInputChannelPair(name);}public String getName() {String name = nativeGetName();return name != null ? name : "uninitialized";}......public void dispose() {nativeDispose(false);}......public void transferTo(InputChannel outParameter) {if (outParameter == null) {throw new IllegalArgumentException("outParameter must not be null");}nativeTransferTo(outParameter);}......
}

1、从java层的InputChannel类可以看出,该类的核心实现都是由native jni层完成的。因此接下来我们主要从Native层讲述InputChannel的实现原理;

2、mPtr 保存native层对应的对象地址;

3、可序列化,InputChannel对象可以跨组件传递;

InputChannel 方法

由于我们本系列的博客讲述Android Input输入管理框架,下面的讲述中,只讲述设计到Input输入管理的关键方法实现。

1、openInputChannelPair

openInputChannelPair的实现如下所示:

 public static InputChannel[] openInputChannelPair(String name) {......return nativeOpenInputChannelPair(name);}

该方法本质上直接调用了jni方法nativeOpenInputChannelPair,如下所示:

static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,jclass clazz, jstring nameObj) {......sp<InputChannel> serverChannel;sp<InputChannel> clientChannel;status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);......// 创建两个InputChannel 空java对象jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);if (env->ExceptionCheck()) {return NULL;}jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,new NativeInputChannel(serverChannel));if (env->ExceptionCheck()) {return NULL;}jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,new NativeInputChannel(clientChannel));if (env->ExceptionCheck()) {return NULL;}// 初始化数组对象env->SetObjectArrayElement(channelPair, 0, serverChannelObj);env->SetObjectArrayElement(channelPair, 1, clientChannelObj);// 返回创建的2个java层对象return channelPair;
}

nativeOpenInputChannelPair方法主要完成如下的逻辑:

1、创建一个网络socket对套接字,分别由serverChannel和clientChannel进行管理,这部分源码不再展开详细讲解;

2、创建java层的InputChannel两个数组对象;

3、创建serverChannel和clientChannel InputChannel 对象,并分别设置server和client的native层的对象地址;

4、初始化第2步创建的java数组对象,然后将该数组对象返回java空间;

2、transferTo

transferTo的方法实现如下所示:

public void transferTo(InputChannel outParameter) {......nativeTransferTo(outParameter);}

改方法直接调用了nativeTransferTo,如下所示:

/*** 将自己的native C++对象绑定给otherObj的native C++上,然后清空自己的native对象*/
static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,jobject otherObj) {if (android_view_InputChannel_getNativeInputChannel(env, otherObj) != NULL) {jniThrowException(env, "java/lang/IllegalStateException","Other object already has a native input channel.");return;}// 获的调用对象的native对象地址NativeInputChannel* nativeInputChannel =android_view_InputChannel_getNativeInputChannel(env, obj);// 将otherObj对象的native地址设置为调用对象的nativeInputChannelandroid_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel);// 清空调用对象的native对象地址android_view_InputChannel_setNativeInputChannel(env, obj, NULL);
}

nativeTransferTo的实现逻辑细节,我们不再展开描述,该方法的主要功能就是将otherObj 对象的native层的C++地址替换为调用该方法的InputChannel对象的native层的地址;

3、dispose

dispose的实现方法,如下所示:

 public void dispose() {nativeDispose(false);}

该方法也是直接调用native方法,如下所示:

static void android_view_InputChannel_nativeDispose(JNIEnv* env, jobject obj, jboolean finalized) {NativeInputChannel* nativeInputChannel =android_view_InputChannel_getNativeInputChannel(env, obj);if (nativeInputChannel) {if (finalized) {ALOGW("Input channel object '%s' was finalized without being disposed!",nativeInputChannel->getInputChannel()->getName().string());}nativeInputChannel->invokeAndRemoveDisposeCallback(env, obj);android_view_InputChannel_setNativeInputChannel(env, obj, NULL);// 删除C++对象delete nativeInputChannel;}
}

该方法的实现细节,我们不再展开描述,它的主要功能就是释放native层的InputChannel对象。

总结

本文为Android Input框架中App和Input 服务进行通信的桥梁InputChannel,本质上就是就是对linux中unix域 Socket进程间通信的封装,Framework层调用java层的InputChannel方法,而该方法的核心实现都处于native层。下一篇讲述App如何使用InputChannel与input系统服务建立链接。

相关文章:

Android7 Input(六)InputChannel

概述: 本文讲述Android Input输入框架中 InputChannel的功能。从前面的讲述&#xff0c;我们知道input系统服务最终将输入事件写入了InputChannel&#xff0c;而input属于system_server进程&#xff0c;App属于另外一个进程&#xff0c;当Input系统服务想要把事件传递给App进行…...

【Java ee初阶】初始网络

一、IP地址 概念 IP地址主要用于标识网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址。简单说&#xff0c;IP地址用于定位主机的网络地址。 就像我们发送快递一样&#xff0c;需要知道对方的收货地址&#xff0c;快递员才能将包裹送到目的地。 格式 IP…...

LabVIEW 2019 与 NI VISA 20.0 安装及报错处理

在使用 Windows 11 操作系统的电脑上&#xff0c;同时安装了 LabVIEW 2019 32 位和 64 位版本的软件。此前安装的 NI VISA 2024 Q1 版&#xff0c;该版本与 LabVIEW 2019 32 位和 64 位不兼容&#xff0c;之后重新安装了 NI VISA 20.0。从说明书来看&#xff0c;NI VISA 20.0 …...

http协议理解

文章目录 http协议理解基本概念HTTP版本演变版本编年史版本对比未来趋势 HTTP请求/响应结构请求报文响应报文HTTP方法分类对比方法选择原则必须遵守的约束 常见状态码HTTP头部字段HTTPSHTTPS 核心功能说明HTTPS 如何工作&#xff1f; HTTP特点补充知识点启用HTTP/2Nginx 中配置…...

typecho中的Widget设计文档

组成系统的最基本元素 什么是Widget Widget是组成Typecho的最基本元素&#xff0c;除了已经抽象出来的类库外&#xff0c;其它几乎所有的功能都会通过Widget来完成。在实践中我们发现&#xff0c;在博客这种小型但很灵活的系统中实施一些大型框架的思想是不合适的&#xff0c…...

使用ESPHome烧录固件到ESP32-C3并接入HomeAssistant

文章目录 一、安装ESPHome二、配置ESP32-C3控制灯1.主配置文件esp32c3-luat.yaml2.基础通用配置base.yaml3.密码文件secret.yaml4.围栏灯four_light.yaml5.彩灯rgb_light.yaml6.左右柱灯left_right_light.yaml 三、安装固件四、HomeAssistant配置ESPHome1.直接访问2.配置ESPHom…...

基于STM32、HAL库的CH340N USB转UART收发器 驱动程序设计

一、简介: CH340N是南京沁恒电子生产的一款USB转串口芯片,具有以下特点: 支持USB 2.0全速(12Mbps) 内置时钟,无需外部晶振 支持5V和3.3V电源电压 提供常用的MODEM联络信号 内置上电复位电路 支持Windows/Linux/Mac OSX等多平台驱动 体积小,SOP-8封装 二、硬件接口: CH…...

Spring Boot Controller 如何处理HTTP请求体

Spring Boot (通过Spring MVC) 提供了强大的机制来处理不同 Content-Type​ 的HTTP请求体。这主要依赖于 HttpMessageConverter​ 接口的各种实现&#xff0c;它们能够自动将请求体内容转换成Java方法参数。 一、核心机制&#xff1a;HttpMessageConverter​ Spring MVC会根据…...

【deepseek教学应用】001:deepseek如何撰写教案并自动实现word排版

本文讲述利用deepseek如何撰写教案并自动实现word高效完美排版。 文章目录 一、访问deepseek官网二、输入教案关键词三、格式转换四、word进一步排版 一、访问deepseek官网 官网&#xff1a;https://www.deepseek.com/ 进入主页后&#xff0c;点击【开始对话】&#xff0c;如…...

【Spring Boot 多模块项目】@MapperScan失效、MapperScannerConfigurer 报错终极解决方案

在使用 Spring Boot 构建多模块项目&#xff0c;集成 MyBatis-Plus 时&#xff0c;很多开发者会遇到类似如下启动报错&#xff1a; Error creating bean with name mapperScannerConfigurer ... Caused by: java.lang.IllegalArgumentException: Property basePackage is requ…...

vue 中如何使用region?

vue 中如何使用region&#xff1f; 在 Vue 文件中&#xff0c;你可以使用 //#region 和 //#endregion 注释来创建可折叠的代码区块&#xff08;类似于 C# 的 region&#xff09;。这可以显著提高大型 Vue 组件的可读性。 1. 基本用法 在 <script> 部分使用 <script&…...

Spring Boot 启动原理的核心机制

一、核心启动流程概览 Spring Boot 的启动流程可概括为 ​7 个关键阶段​&#xff1a; 1. 加载启动类 (Main Class) 2. 初始化 SpringApplication 实例 3. 加载配置 & 准备环境 (Environment) 4. 创建 ApplicationContext&#xff08;容器&#xff09; 5. 刷新容器&#…...

【每天学习一点点】使用Python的pathlib模块分割文件路径

使用Python的pathlib模块分割文件路径 pathlib模块&#xff08;Python 3.4&#xff09;提供了面向对象的文件系统路径操作方式&#xff0c;比传统的os.path更加直观和易用。以下是使用pathlib分割文件路径的几种方法&#xff1a; 基本路径分割 from pathlib import Path# 创…...

Qt/C++面试【速通笔记八】—Qt的事件处理机制

在Qt中&#xff0c;事件处理机制是应用程序与用户或系统交互的核心。通过事件处理&#xff0c;Qt能够响应用户的输入、窗口的变化、定时器的触发等各种情况。 1. 事件循环&#xff08;Event Loop&#xff09; 在Qt应用程序中&#xff0c;事件循环是事件处理机制的基础。事件循…...

uniapp自定义步骤条(可二开进行调试)

前言 有一个业务需求是需要一个步骤条&#xff0c;但是发现开源的都不太合适&#xff0c;所以就自己写了一个。 开始 test.vue <template><view class"authenticateRecordDetails_container"><!-- 进度 --><view class"authenticateSte…...

uniapp|实现多终端聊天对话组件、表情选择、消息发送

基于UniApp框架,实现跨平台多终端适配的聊天对话组件开发、表情选择交互设计及消息发送,支持文本与表情混合渲染。 目录 聊天界面静态组件实现消息列表布局消息气泡双向布局辅助元素定位与样式静态数据模拟与扩展性设计表情选择器静态模块浮层实现符号网格排列多端样式适配方…...

1.3.1 Linux音频框架alsa详细介绍

ALSA作为对旧OSS系统的替代方案&#xff0c;始于1998年。当时OSS还闭源商业化&#xff0c;因此社区开始开发开源的ALSA。经过多年的发展&#xff0c;ALSA成为Linux内核中音频架构的标准。 结构和架构 ALSA由以下几个主要部分组成&#xff1a; 内核模块&#xff1a; 这是ALSA的…...

R 语言机器学习:为遥感数据处理开启新视角

技术点目录 基础理论、机器学习与数据准备建模与空间预测实践案例与项目了解更多 ——————————————————————————————————————————— 前言综述 在当今科技快速发展的时代&#xff0c;遥感技术为生态学研究提供了海量的数据资源&#xf…...

深度 |提“智”向新,奔向未来——当前机器人产业观察

机器人踏着“猫步”在T台走秀、进入工厂协助造车&#xff0c;教育、医疗、城市管理等领域都有了机器人的帮助……今天&#xff0c;机器人已得到广泛应用&#xff0c;走进你我的生活。    伴随着技术日新月异&#xff0c;机器人产业加快提“智”向新。特别是今年以来&#xf…...

Web开发-JavaEE应用SpringBoot栈ActuatorSwaggerHeapDump提取自动化

知识点&#xff1a; 1、安全开发-JavaEE-常见依赖-Actuator&Swagger 2、安全开发-JavaEE-安全问题-配置安全&接口测试 一、演示案例-WEB开发-JavaEE-监控依赖-SpringBoot&Actuator&配置安全 SpringBoot Actuator模块提供了生产级别的功能&#xff0c;比如健康…...

AI Agent开发之门:微软官方课程全面解析

AI Agent开发之门&#xff1a;微软官方课程全面解析 引言项目概览10 节核心课程内容详解1. AI 代理简介及应用场景2. 探索 AI Agentic 框架3. 理解 AI Agentic 设计模式4. 工具使用设计模式5. Agentic RAG&#xff08;检索增强生成&#xff09;6. 构建可信赖的 AI Agents7. 规划…...

Unity-Shader详解-其五

关于Unity的Shader部分的基础知识其实已经讲解得差不多了&#xff0c;今天我们来一些实例分享&#xff1a; 溶解 效果如下&#xff1a; 代码如下&#xff1a; Shader "Chapter8/chapter8_1" {Properties{// 定义属性[NoScaleOffset]_Albedo("Albedo", 2…...

从零打造个人博客静态页面与TodoList应用:前端开发实战指南

前言 在当今数字时代&#xff0c;拥有个人博客和高效的任务管理工具已成为开发者展示自我和提升生产力的标配。本文将带你从零开始&#xff0c;通过纯前端技术实现一个兼具个人博客静态页面和TodoList任务管理功能的综合应用。无论你是前端新手还是希望巩固基础的中级开发者&a…...

开发者如何优雅应对HTTPS抓包难题

开发者如何优雅应对HTTPS抓包难题&#xff1a;工具实战 深度解析 调试HTTPS接口这件事&#xff0c;真是程序员永远的痛。特别是在移动端、或者遇到客户端集成了第三方安全SDK的项目时&#xff0c;网络调试的门槛几乎成倍提升。你可能也遇到过&#xff1a;Charles不识别证书、…...

Ubuntu 安装远程桌面连接RDP方式

1. 安装 XFCE4 桌面环境 如果你的 Ubuntu 系统默认使用 GNOME 或其它桌面环境&#xff0c;可以安装轻量级的 XFCE4&#xff1a; sudo apt update sudo apt install xfce4 xfce4-goodies 说明&#xff1a;xfce4-goodies 包含额外的插件和工具&#xff08;如面板插件、终端等&a…...

Ubuntu 22.04 出现 ‘Temporary failure resolving‘ 解决方案

a、使用apt 安装 resolvconf sudo apt-get install resolvconf b、使用 cd /etc/resolvconf/resolv.conf.d/ 进入文件夹&#xff0c;使用 ls 查看目录&#xff0c;会显示 base head tail c、使用 sudo vim base 编辑base文件&#xff0c; 进入时为空&#xff0c;添加 name…...

ubuntu 22.04 换源

参考&#xff1a;清华大学开源软件镜像站 ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror...

Java并发编程几个问题的解答

目录 1、以前你编写的Java程序同时能做几件事情&#xff1f;有几个执行流程&#xff1f;main方法执行完&#xff0c;整个程序一定会退出吗&#xff1f;2、早期的电脑一般是单核CPU&#xff0c;但那时我们就可以在编写程序的同时听歌&#xff0c;你觉得其CPU可以同时执行两个程序…...

JavaScript中数组和对象不同遍历方法的顺序规则

在JavaScript中&#xff0c;不同遍历方法的顺序规则和适用场景存在显著差异。以下是主要方法的遍历顺序总结&#xff1a; 一、数组遍历方法 for循环 • 严格按数组索引顺序遍历&#xff08;0 → length-1&#xff09; • 支持break和continue中断循环 • 性能最优&#xff0c;…...

C++ STL入门:set 集合容器

C STL入门&#xff1a;set 集合容器 一、核心特性与适用场景 set 是 C STL 提供的关联式容器&#xff0c;基于红黑树实现&#xff0c;具有两大核心特性&#xff1a; 特性表现形式底层原理元素唯一性重复值自动去重插入时进行二叉树键比对自动排序元素默认升序排列红黑树中序遍…...

[论文笔记] 超详细解读DeepSeek v3全论文技术报告

DeepSeek-V3是一个强大的专家混合(Mixture-of-Experts,MoE)语言模型,总共671B参数,每个token激活37B参数(可以理解为有多个专家,但每个token只会选择一部分专家进行推理,所以一个token的预测,只会用到37B参数),DeepSeek-V3 使用了 多头潜在注意力(...

JS 问号(?)运算符避免中间报错

一、场景 在前端开发过程中&#xff0c;有一些情况比如某些属性可能由于渲染数据的时机不同&#xff0c;一开始是null 或者undifine, 这样访问下面的属性的时候就会报错&#xff0c;我们可以给每个层级后面加个? 就可以避免这个错误。 let data {user: {profile: {name: &q…...

4:点云处理—去噪、剪切、调平

1.点云去噪 dev_clear_window ()dev_open_window(0, 0, 560, 560, black, WindowHandle)GenParamNames : [lut,intensity,light_position,disp_pose,alpha]GenParamValues : [color1,coord_z,0.0 0.0 -0.3 1.0,true,1]DispPose : [0,-0.0005,717.04,280,0,20,0]Instructions[0]…...

机器学习实操 第二部分 神经网路和深度学习 第17章 编码器、生成对抗网络和扩散模型

机器学习实操 第二部分 神经网路和深度学习 第17章 编码器、生成对抗网络和扩散模型 内容概要 第17章深入探讨了自编码器&#xff08;Autoencoders&#xff09;、生成对抗网络&#xff08;GANs&#xff09;和扩散模型&#xff08;Diffusion Models&#xff09;。这些模型能够…...

【今日三题】ISBN号码(模拟) / kotori和迷宫(BFS最短路) / 矩阵最长递增路径(dfs)

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;每日两三题 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 ISBN号码(模拟)kotori和迷宫(BFS最短路)矩阵最长递增路径(dfs) ISBN号码(模拟) ISBN号码 #include <iostream> #incl…...

【记录】HunyuanVideo 文生视频工作流

HunyuanVideo 文生视频工作流指南 概述 本指南详细介绍如何在ComfyUI中使用腾讯混元HunyuanVideo模型进行文本到视频生成的全流程操作&#xff0c;包含环境配置、模型安装和工作流使用说明。 参考&#xff1a;https://comfyui-wiki.com/zh/install/install-comfyui/install-c…...

DevExpressWinForms-布局之TablePanel

布局之TablePanel 在 DevExpress 的控件库中&#xff0c;TablePanel 是一个功能强大且灵活的布局控件&#xff0c;它能够以表格形式组织和排列其他控件&#xff0c;让界面布局更加规整、有序。无论是开发复杂的企业级应用程序&#xff0c;还是设计简洁美观的用户界面&#xff…...

MySQL 数据库初体验

目录 1.1 数据库简介 1.1.1 使用数据库的必要性 1.1.2 数据库的基本概念 1.数据 2.数据库和数据库表 3.数据库管理系统和数据库系统 1.1.3 数据库发展史 1.数据库系统发展史 &#xff08;1&#xff09;初级阶段——第一代数据库 &#xff08;2&#xff09;中级阶段—…...

flink超时未揽收单量统计

应用场景&#xff1a; 双十一大屏统计 - - 订单超时汇总 项目指标概况&#xff1a; 应用背景&#xff1a;晚点超时指标&#xff0c;例如&#xff1a;出库超6小时未揽收订单量 难点&#xff1a;flink消息触发式计算&#xff0c;没有消息到达则无法计算&#xff0c;而这类指标…...

【造包工具】【Xcap】精讲Xcap构造分片包(IPv4、ipv6、4G\5G等pcap均可),图解超赞超详细!!!

目录 前言 1. XCap工具概念介绍 2. Xcap环境说明 2.1 新建报文组 2.2 导入数据包 2.3 查看报文组 2.4 复制删除报文组 3. 构造分片包 3.1 造普通/外层分片步骤&#xff1a; 3.2 造内层分片步骤 3.2.1 建立一个新报文 3.2.2 将组装的新报文分片 3.2.3 替换原始包内层…...

RabbitMQ学习(第二天)

文章目录 1、生产者可靠性①、生产者重连②、生产者确认 2、MQ可靠性①、数据持久化②、LazyQueue(惰性队列) 3、消费者可靠性①、消费者确认②、失败重试机制③、保证业务幂等性 总结 之前的学习中&#xff0c;熟悉了java中搭建和操作RabbitMQ发送接收消息&#xff0c;熟悉使用…...

旧版 Flutter 写的项目, 想要在新的环境上运行?

DeepSeek 给出的最佳实践 以下是针对拷贝 Flutter 项目到新环境运行的 完整检查清单和最佳实践&#xff0c;覆盖了环境配置、版本兼容性、依赖管理等多个关键点&#xff1a; &#x1f4cb; 完整检查清单 检查项操作方式/命令重要性1. Flutter SDK 版本flutter --version 对比…...

Flutter接入ProtoBuff和原生Android通信【性能最优】

Protocol Buffers&#xff08;简称Protobuf&#xff09;是由 Google 开发的一种结构化数据序列化框架&#xff0c;旨在实现高效的数据交换与存储。其核心特性及优势如下&#xff1a; 一、核心特性 ‌跨语言与跨平台‌ 支持多种编程语言&#xff08;如 C、Java、Python、Dart …...

【MySQL】(10)用户和权限管理

一、应用场景 通常一个应用对应一个数据库&#xff0c;我们希望某个数据库只能被相关人员操纵&#xff0c;就需要创建用户并指定权限。只有登录该用户&#xff0c;才能在权限范围内操纵数据库。root 是权限最高的用户&#xff0c;它拥有所有的权限。 二、查询用户 在 mysql 数…...

学成在线之缓存

一&#xff1a;缓存 把白名单可以看到的信息和学生用户下的我的学习&#xff0c;我的选课等这些信息&#xff0c;存到缓存中&#xff0c;因为这些查询量比较大。 当查询时&#xff0c;先去检查缓存中是否有这个数据&#xff0c;如果有&#xff0c;就直接返回 如果没有&#…...

视频编解码学习8之视频历史

视频技术的发展历史可以追溯到19世纪&#xff0c;至今已跨越近200年。以下是视频技术发展的主要阶段和里程碑&#xff1a; 1. 早期探索阶段&#xff08;19世纪-1920年代&#xff09; 1832年&#xff1a;约瑟夫普拉托&#xff08;Joseph Plateau&#xff09;发明"费纳奇镜&…...

从装饰器出发,优雅处理 UI 自动化中的异常

二、装饰器核心原理&#xff1a;函数式编程的“语法糖” 在 UI 自动化测试的实际场景中&#xff0c;页面加载超时、元素定位失败、网络波动等异常问题频繁出现。传统的try-except嵌套方式虽然能捕获异常&#xff0c;但会导致业务代码与处理逻辑高度耦合&#xff0c;造成代码冗…...

华为首款鸿蒙电脑正式亮相

在2025年5月8日的鸿蒙电脑技术与生态沟通会上&#xff0c;华为终端BG平板与PC产品线总裁朱懂东发表演讲。鸿蒙办公将支持无缝协同&#xff08;统一账户 / 多端同步&#xff09;、智慧体验&#xff08;鸿蒙 AI / 智慧交互&#xff09;、融合生态&#xff08;桌面生态 / 移动生态…...

森林生态学研究深度解析:R语言入门、生物多样性分析、机器学习建模与群落稳定性评估

在生态学研究中&#xff0c;森林生态系统的结构、功能与稳定性是核心研究内容之一。这些方面不仅关系到森林动态变化和物种多样性&#xff0c;还直接影响森林提供的生态服务功能及其应对环境变化的能力。森林生态系统的结构主要包括物种组成、树种多样性、树木的空间分布与密度…...

需求分析阶段测试工程师主要做哪些事情

在软件测试需求分析阶段&#xff0c;主要围绕确定测试范围、明确测试目标、细化测试内容等方面开展工作&#xff0c;为后续测试计划的制定、测试用例的设计以及测试执行提供清晰、准确的依据。以下是该阶段具体要做的事情&#xff1a; 1. 需求收集与整理 收集需求文档&#x…...