android自动化测试中hierarchyviewer和uiautomatorviewer获取控件信息的方式比对(1)
请关注我的微信公众号
android自动化新人一个,目前研究PC端获取android设备的控件信息有哪些方式。多多指教!
android的目录tools下有2个自带的工具hierarchyviewer和uiautomatorviewer,打开后,如下所示:
分别来介绍它们怎么使用的:
UiAutoMatorViewer
点击左上角的手机图样的小图标,出现弹出框,此时正在获取信息:
完成获取后得到了当前的手机界面:
然后你可以点击主面板中的图片,右面的属性面板会显示你所点击的区域的控件属性。(需要注意到是,你的手机设备或模拟器的api要在16以上,也就是android版本得是4.1以上,因为这个工具是google在4.以后推出来的,只适用于4.1以后的版本)。
到这一步,我了解了如何使用这个工具,但是并不是我要研究的东西。我要知道他是如何和手机设备通信,然后获取控件信息的,所以我反编译了uiautomatorviewer.jar,以便从源码了解它的原理。
在tools/lib下找到uiautomatorviewer.jar。反编译后项目结构如下所示:
首先查看UiAutomatorViewer.class,打开后明显看出这是一个java.swt的主界面类,那我们只需要找到工具栏中的按钮的定义。我们就能追踪到点击它是怎么得到设备控件信息的。
找到这个按钮的定义后,我们按ctrl键 点击鼠标跟踪进去,发现该类中有一个进度条对话框,这正是我们先前点击按钮出现的对话框,这里面肯定定义信息获取的方式。
查看上面的代码分析得到,UiAutoMatorHelper的子类UiAutoMatorResult和对象result,它得到了UiAutomatorHelper方法和takeSnapShot返回的结果,那么我就去这个方法一探究竟。进入UiAutomatorHelper中,找到takeSnapshot方法。
public static UiAutomatorResult takeSnapshot(IDevice device, IProgressMonitor monitor) throws com.android.uiautomator.UiAutomatorHelper.UiAutomatorException{UiAutomatorModel model;String msg;RawImage rawImage;if (monitor == null) {monitor = new NullProgressMonitor();}monitor.subTask("Checking if device support UI Automator");if (!(supportsUiAutomator(device))) {String msg = "UI Automator requires a device with API Level 16";throw new com.android.uiautomator.UiAutomatorHelper.UiAutomatorException(msg, null);}monitor.subTask("Creating temporary files for uiautomator results.");File tmpDir = null;File xmlDumpFile = null;File screenshotFile = null;try {tmpDir = File.createTempFile("uiautomatorviewer_", "");tmpDir.delete();if (!(tmpDir.mkdirs()))throw new IOException("Failed to mkdir");xmlDumpFile = File.createTempFile("dump_", ".uix", tmpDir);screenshotFile = File.createTempFile("screenshot_", ".png", tmpDir);} catch (Exception e) {msg = "Error while creating temporary file to save snapshot: " + e.getMessage();throw new com.android.uiautomator.UiAutomatorHelper.UiAutomatorException(msg, e);}tmpDir.deleteOnExit();xmlDumpFile.deleteOnExit();screenshotFile.deleteOnExit();monitor.subTask("Obtaining UI hierarchy");try {<span style="color:#ff0000;">getUiHierarchyFile(device, xmlDumpFile, monitor);
</span> } catch (Exception e) {msg = "Error while obtaining UI hierarchy XML file: " + e.getMessage();throw new com.android.uiautomator.UiAutomatorHelper.UiAutomatorException(msg, e);}
刚开始的时候没明白为什么有好多定义文件的代码,然后就没管,往下看的时候发现了一个getUiHierarchyFile方法,既然在这个方法里没找到获取控件信息的方式,那么我就试着去getUiherarchyFile方法中看看(其实我之前研究hierarchyviewer的时候,这个工具也用过这个getHierarchy方法,只不过叫parseHierarchy,它就是获取控件树的,所以我心中一喜,有戏) 。让我们进入getUiHerarchyFile中看看,看能否发现我们真正需要的。
private static void getUiHierarchyFile(IDevice device, File dst, IProgressMonitor monitor) {if (monitor == null) {monitor = new NullProgressMonitor();}monitor.subTask("Deleting old UI XML snapshot ...");String command = "rm /data/local/tmp/uidump.xml";try{commandCompleteLatch = new CountDownLatch(1);device.executeShellCommand(command, new CollectingOutputReceiver(commandCompleteLatch));commandCompleteLatch.await(5L, TimeUnit.SECONDS);}catch (Exception e1){}monitor.subTask("Taking UI XML snapshot...");command = String.format("%s %s %s", new Object[] { "/system/bin/uiautomator", "dump", "/data/local/tmp/uidump.xml" });CountDownLatch commandCompleteLatch = new CountDownLatch(1);try{device.executeShellCommand(command, new CollectingOutputReceiver(commandCompleteLatch), 40000);commandCompleteLatch.await(40L, TimeUnit.SECONDS);monitor.subTask("Pull UI XML snapshot from device...");device.getSyncService().pullFile("/data/local/tmp/uidump.xml", dst.getAbsolutePath(), SyncService.getNullProgressMonitor());}catch (Exception e) {throw new RuntimeException(e);}}
</pre><pre code_snippet_id="250249" snippet_file_name="blog_20140322_3_2829642" class="html" name="code">
我原本以为这里面也应该有个socke啥的,跟手机端通信获取数据的。进来这里面没发现socket,但是仔细一分析,原来UiAutomatorviewer并不是通过socket来获取信息的。它是发送dump命令,让存放在手机设备中/system/bin/uiautomator下的脚本执行,获得一个uidump.xml的文件,然后将这个文件抓到本地。本地读取xml文件就可以了。这才恍然大悟为什么之前takeSnapshot方法中有定义文件的操作,原来它是通过获取xml文件存放在本地临时文件里,太鬼了。
那剩下的就是读取xml文件喽。到这,我的uiautomatorviewer的了解就结束了,还算有点收获。下面接着hierarchyviewer的使用。
HierarchyViewer
说到hierarchyviewer都是眼泪,花了3个礼拜研究,由于自己的死心眼,非要通过它实现自动化,非要用java写。然后一直研究到它可以遍历settings的所有界面;然后才发现被坑了,代码太长了;if/else写了一大堆,又是dumpsys命令获取window信息和activity信息,又是图片比对确定点击跳转的图片,然后满心欢喜的拿给经理看,经理直接给否决了---效率太低;hierarchyviewer获取数据确实慢,但是总算有的基础版本的嘛;其实我发现经理心里算盘打着好着呢,她只是让我们一步一步的了解,她知道哪种方式最适合,就是还不告诉我们,就让我们自己研究,而我呢,刚来又着急展示一下,根基没打稳就像往大的方向走,都开始实现开啦;然后被经理给拽回来, 开始研究哪些实现获取控件的方式,以及优缺点,这才有了上面的uiautomator的研究;哎,不着急,一步一步来吧。
说到hierarchyviewer,研究起来真的是小孩学步啊。经理只丢了一个命题:多语自动化测试,你们研究吧。我ca类,我还傻不垃圾的问了一句:什么是多语。旁边的测试人员给我回答了,多国语言测试。汗!好吧,我低端。。。。。。开始吧。
首先选择是手机端直接测试,还是连上PC端测试?然后发现了monkey,再到monkeyrunner,然后在monkeyrunner里有touch方法点击,然后却不知道一个按钮的坐标怎么确定,在一个犄角旮旯的地方发现有人说通过hierarchyviewer可以获取坐标。然后就开始一个坐标一个坐标的找啊,编写脚本啊。总算实现了一点:唤醒--解锁--点--点--点;然后开讨论会的时候,让经理否决了,说是这么多控件,要一个一个找,得多长时间啊。要做到连上手机,不管哪个画面,它自己获得,然后点击。确实高端大气上档次!but你倒是告诉我从那块搞起啊。哎,在百般纠结于无奈中,柳暗花明啦,hierarchyviewer上的东西不就是人家从客户端获取的么。得到这个讯息后,我找到了一个知平软件写的,然后根据他的研究,一步一步了解了hierarchyviewer,在此感谢这个前辈,放出连接,新手同学可以研究下。
第一篇:http://www.cnblogs.com/vowei/archive/2012/07/30/2614353.html
第二篇:http://www.cnblogs.com/vowei/archive/2012/08/03/2618753.html
第三篇:http://www.cnblogs.com/vowei/archive/2012/08/08/2627614.html
第四篇:http://www.cnblogs.com/vowei/archive/2012/08/22/2650722.html
通过读这四篇文章,我对hierarchyviewer有了一定了解,对于这位前辈没给出的一些疑惑我做了一些深入的研究和总结。
总结:
1.hierarchyviewer是通过socket连接android设备的ViewServer,通过4939端口建立通信。
2.通过adb -s <device> forward tcp:localpott tcp:4939将端口映射到本地端口上
3.通过该本地端口,客户端启动socket连接ViewServer,发送"dump -1"命令获取控件信息。这些信息一行代表一个控件,然后存放在ViewNode中。
以上通过上面四篇文章你都能了解到。下面是自己的疑问:
1.信息是如何从一行一行的字符串转变为viewnode对象的。
2.是怎么深度遍历树的。
带着这些疑问我又暴力了,反编译hierarchyviewer2lib.jar文件,寻找到了DeviceBridge的parseHierarchy方法:
public static ViewNode parseViewHierarchy(BufferedReader in, Window window) {ViewNode currentNode = null;int currentDepth = -1;try{while ((line = in.readLine()) != null) {String line;if ("DONE.".equalsIgnoreCase(line))break;int depth = 0;while (line.charAt(depth) == ' ')++depth;while (depth <= currentDepth) {if (currentNode != null)currentNode = currentNode.parent;--currentDepth;}<span style="color:#ff6666;">currentNode = new ViewNode(window, currentNode, line.substring(depth));
</span> currentDepth = depth;}} catch (IOException e) {Log.e("hierarchyviewer", "Error reading view hierarchy stream: " + e.getMessage());return null;}if (currentNode == null)return null;while (currentNode.parent != null) {currentNode = currentNode.parent;}return currentNode;}
通过标红的代码可知,创建ViewNode对象的时候,传入三个参数:window,currentNode,读取的行数据去掉空格后的line.找到ViewNode类。
package com.android.hierarchyviewerlib.models;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.swt.graphics.Image;public class ViewNode
{private static final double RED_THRESHOLD = 0.80000000000000004D;private static final double YELLOW_THRESHOLD = 0.5D;public static final String MISCELLANIOUS = "miscellaneous";public String id;public String name;public String hashCode;public List<Property> properties = new ArrayList();public Map<String, Property> namedProperties = new HashMap();public ViewNode parent;public List<ViewNode> children = new ArrayList();public int left;public int top;public int width;public int height;public int scrollX;public int scrollY;public int paddingLeft;public int paddingRight;public int paddingTop;public int paddingBottom;public int marginLeft;public int marginRight;public int marginTop;public int marginBottom;public int baseline;public boolean willNotDraw;public boolean hasMargins;public boolean hasFocus;public int index;public double measureTime;public double layoutTime;public double drawTime;public ProfileRating measureRating = ProfileRating.NONE;public ProfileRating layoutRating = ProfileRating.NONE;public ProfileRating drawRating = ProfileRating.NONE;public Set<String> categories = new TreeSet();public Window window;public Image image;public int imageReferences = 1;public int viewCount;public boolean filtered;public int protocolVersion;public ViewNode(Window window, ViewNode parent, String data){<span style="color:#ff6666;">this.window = window;this.parent = parent;this.index = ((this.parent == null) ? 0 : this.parent.children.size());if (this.parent != null)this.parent.children.add(this);int delimIndex = data.indexOf(64);if (delimIndex < 0)throw new IllegalArgumentException("Invalid format for ViewNode, missing @: " + data);this.name = data.substring(0, delimIndex);data = data.substring(delimIndex + 1);delimIndex = data.indexOf(32);this.hashCode = data.substring(0, delimIndex);if (data.length() > delimIndex + 1) {loadProperties(data.substring(delimIndex + 1).trim());}else {this.id = "unknown";this.width = (this.height = 10);}</span> this.measureTime = -1.0D;this.layoutTime = -1.0D;this.drawTime = -1.0D;}public void dispose() {int N = this.children.size();for (int i = 0; i < N; ++i)((ViewNode)this.children.get(i)).dispose();dereferenceImage();}public void referenceImage() {this.imageReferences += 1;}public void dereferenceImage() {this.imageReferences -= 1;if ((this.image != null) && (this.imageReferences == 0))this.image.dispose();}private void loadProperties(String data){boolean stop;int start = 0;do{int index = data.indexOf(61, start);Property property = new Property();property.name = data.substring(start, index);int index2 = data.indexOf(44, index + 1);int length = Integer.parseInt(data.substring(index + 1, index2));start = index2 + 1 + length;property.value = data.substring(index2 + 1, index2 + 1 + length);this.properties.add(property);this.namedProperties.put(property.name, property);stop = start >= data.length();if (!(stop))++start;}while (!(stop));Collections.sort(this.properties, new Comparator(this){public int compare(, ViewNode.Property destination) {return source.name.compareTo(destination.name);}});this.id = ((Property)this.namedProperties.get("mID")).value;this.left = ((this.namedProperties.containsKey("mLeft")) ? getInt("mLeft", 0) : getInt("layout:mLeft", 0));this.top = ((this.namedProperties.containsKey("mTop")) ? getInt("mTop", 0) : getInt("layout:mTop", 0));this.width = ((this.namedProperties.containsKey("getWidth()")) ? getInt("getWidth()", 0) : getInt("layout:getWidth()", 0));this.height = ((this.namedProperties.containsKey("getHeight()")) ? getInt("getHeight()", 0) : getInt("layout:getHeight()", 0));this.scrollX = ((this.namedProperties.containsKey("mScrollX")) ? getInt("mScrollX", 0) : getInt("scrolling:mScrollX", 0));this.scrollY = ((this.namedProperties.containsKey("mScrollY")) ? getInt("mScrollY", 0) : getInt("scrolling:mScrollY", 0));this.paddingLeft = ((this.namedProperties.containsKey("mPaddingLeft")) ? getInt("mPaddingLeft", 0) : getInt("padding:mPaddingLeft", 0));this.paddingRight = ((this.namedProperties.containsKey("mPaddingRight")) ? getInt("mPaddingRight", 0) : getInt("padding:mPaddingRight", 0));this.paddingTop = ((this.namedProperties.containsKey("mPaddingTop")) ? getInt("mPaddingTop", 0) : getInt("padding:mPaddingTop", 0));this.paddingBottom = ((this.namedProperties.containsKey("mPaddingBottom")) ? getInt("mPaddingBottom", 0) : getInt("padding:mPaddingBottom", 0));this.marginLeft = ((this.namedProperties.containsKey("layout_leftMargin")) ? getInt("layout_leftMargin", -2147483648) : getInt("layout:layout_leftMargin", -2147483648));this.marginRight = ((this.namedProperties.containsKey("layout_rightMargin")) ? getInt("layout_rightMargin", -2147483648) : getInt("layout:layout_rightMargin", -2147483648));this.marginTop = ((this.namedProperties.containsKey("layout_topMargin")) ? getInt("layout_topMargin", -2147483648) : getInt("layout:layout_topMargin", -2147483648));this.marginBottom = ((this.namedProperties.containsKey("layout_bottomMargin")) ? getInt("layout_bottomMargin", -2147483648) : getInt("layout:layout_bottomMargin", -2147483648));this.baseline = ((this.namedProperties.containsKey("getBaseline()")) ? getInt("getBaseline()", 0) : getInt("layout:getBaseline()", 0));this.willNotDraw = ((this.namedProperties.containsKey("willNotDraw()")) ? getBoolean("willNotDraw()", false) : getBoolean("drawing:willNotDraw()", false));this.hasFocus = ((this.namedProperties.containsKey("hasFocus()")) ? getBoolean("hasFocus()", false) : getBoolean("focus:hasFocus()", false));this.hasMargins = ((this.marginLeft != -2147483648) && (this.marginRight != -2147483648) && (this.marginTop != -2147483648) && (this.marginBottom != -2147483648));for (Iterator i$ = this.namedProperties.keySet().iterator(); i$.hasNext(); ) { String name = (String)i$.next();int index = name.indexOf(58);if (index != -1)this.categories.add(name.substring(0, index));}if (this.categories.size() != 0)this.categories.add("miscellaneous");}public void setProfileRatings(){int N = this.children.size();if (N > 1) {ViewNode child;double totalMeasure = 0D;double totalLayout = 0D;double totalDraw = 0D;for (int i = 0; i < N; ++i) {child = (ViewNode)this.children.get(i);totalMeasure += child.measureTime;totalLayout += child.layoutTime;totalDraw += child.drawTime;}for (i = 0; i < N; ++i) {child = (ViewNode)this.children.get(i);if (child.measureTime / totalMeasure >= 0.80000000000000004D)child.measureRating = ProfileRating.RED;else if (child.measureTime / totalMeasure >= 0.5D)child.measureRating = ProfileRating.YELLOW;elsechild.measureRating = ProfileRating.GREEN;if (child.layoutTime / totalLayout >= 0.80000000000000004D)child.layoutRating = ProfileRating.RED;else if (child.layoutTime / totalLayout >= 0.5D)child.layoutRating = ProfileRating.YELLOW;elsechild.layoutRating = ProfileRating.GREEN;if (child.drawTime / totalDraw >= 0.80000000000000004D)child.drawRating = ProfileRating.RED;else if (child.drawTime / totalDraw >= 0.5D)child.drawRating = ProfileRating.YELLOW;elsechild.drawRating = ProfileRating.GREEN;}}for (int i = 0; i < N; ++i)((ViewNode)this.children.get(i)).setProfileRatings();}public void setViewCount(){this.viewCount = 1;int N = this.children.size();for (int i = 0; i < N; ++i) {ViewNode child = (ViewNode)this.children.get(i);child.setViewCount();this.viewCount += child.viewCount;}}public void filter(String text) {int dotIndex = this.name.lastIndexOf(46);String shortName = (dotIndex == -1) ? this.name : this.name.substring(dotIndex + 1);this.filtered = ((!(text.equals(""))) && (((shortName.toLowerCase().contains(text.toLowerCase())) || ((!(this.id.equals("NO_ID"))) && (this.id.toLowerCase().contains(text.toLowerCase()))))));int N = this.children.size();for (int i = 0; i < N; ++i)((ViewNode)this.children.get(i)).filter(text);}private boolean getBoolean(String name, boolean defaultValue){Property p = (Property)this.namedProperties.get(name);if (p != null)try {return Boolean.parseBoolean(p.value);} catch (NumberFormatException e) {return defaultValue;}return defaultValue;}private int getInt(String name, int defaultValue) {Property p = (Property)this.namedProperties.get(name);if (p != null)try {return Integer.parseInt(p.value);} catch (NumberFormatException e) {return defaultValue;}return defaultValue;}public String toString(){return this.name + "@" + this.hashCode;}public static class Property{public String name;public String value;public String toString(){return this.name + '=' + this.value;}}public static enum ProfileRating{RED, YELLOW, GREEN, NONE;}
}
在构造方法中,我了解到了它把传递过来的ViewNode对象作为当前对象的父对象,又把当前对象作为父节点的子节点。形成一个链表结构,这样我通过最上层的根节点就可以获得所有节点(佩服佩服,后悔自己数据结构和算法没学好啊!)。一行currentNode = new ViewNode(window, currentNode, line.substring(depth));解决了所有烦恼,就是理解的时候要花费一点时间。
通过源码的学习。我了解hierarchyviewer的工作方式,然后我动手用java自己来实现。下一篇再续讲,该吃饭了。
下一篇:
android自动化测试中hierarchyviewer和uiautomatorviewer获取控件信息的方式比对(2)
uiautomatorviewer在5.0中的改进
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- Java复习(一)
这里写自定义目录标题一、JVM原理二、JRE三、JDK合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不…...
2024/4/21 17:36:05 - 如何给用containerd启动的kata容器添加网络
如果直接用ctr创建容器,那么容器内部是没有网络的。这是因为containerd属于CRI模块,网络是由CNI组件去完成的,因此要想有网先要搞定cni。 好消息是已经有个非常好的工具可以像docker一样使用containerd的service启动有网络的容器。这就是ner…...
2024/4/21 17:36:07 - 设计架构 | MVVM模型
前言:本文简单介绍了MVVM,作为Vue开发的设计思想,学习MVVM将有助于我们深入理解Vue的目的与原理,是在现有的MVC基础上的扩展。 简介 MVVM (Model-View-ViewModel),响应式编程模型,目的是分离视图 (View) 和…...
2024/4/21 17:36:02 - Android开发笔记(一百二十六)自定义音乐播放器
MediaRecorder/MediaPlayer 在Android手机上面,音频的处理比视频还要复杂,这真是出人意料。在前面的博文《Android开发笔记(五十七)录像录音与播放》中,介绍了视频/音频的录制与播放,其中录像用的是MediaRecorder类,播放用的是MediaPlayer类。虽然Android还提供了专门的…...
2024/4/21 17:36:01 - mac纯前端部署至本地服务器方案
前置环境 应保证服务器上具备nginx环境,若无,则按此教程进行配置 Linux nginx安装篇 具体步骤 一、打包本地项目 在项目目录下执行npm run build 生成dist文件夹 二、在服务器上创建自定义目录,以webapp为例 1.连接服务器 ssh root192.…...
2024/4/21 17:36:01 - mycat高可用集群搭建
高并发项目中我们时长会进行读写分离,多主多从的数据库架构设计,通过mycat中间件进行分库分表的操作,那么在生产环境中为了避免mycat服务的单点故障,所以mycat也需要进行高可用的集群搭建。 一、mycat高可用架构拓扑图 客户端请…...
2024/4/21 17:35:59 - Ubuntu18.04编译gcc-4.9.3
注:主要过程参见:Ubuntu18.04编译安装gcc6.3,这里只说编译过程中此博文没有遇到的问题。 一、问题一 cfns.gperf: 在函数‘const char* libc_name_p(const char*, unsigned int)’中:cfns.gperf:101:1: 错误:‘const char* libc…...
2024/4/20 5:03:15 - 如何正确推广App,实现高转化用户。
个性化深度链接技术的应用。深度链接使网页和App两者串联起来,减少了转换漏斗中的损失。再加上深度链接不仅能改善潜在用户的转化,对沉睡用户的唤醒同样也能发挥关键作用。 类型不含深度链接使用深度链接携带参数首页商品的id号,房间号&…...
2024/4/20 13:52:44 - Deep visual domain adaptation: A survey
摘要 深度视觉域适配作为一个解决大量标注数据缺失的新的学习技巧而出现。与传统的学习共享特征子空间或使用浅层表示重用重要源实例的方法相比,深度域适应方法通过将域适应嵌入深度学习管道中,利用深度网络学习更多可迁移的表示。对于浅域适应的研究已…...
2024/4/20 13:52:43 - S3C2440驱动开发(九)
Bootloader之vivi源码解析(二) 继上面章节后,本节重点介绍vivi常用功能及实现原理。 (1)Load加载命令 加载命令,可以将程序或者文件通过串口加载到RAM和FLASH中,实现程序烧写功能。使用的数据…...
2024/4/20 13:52:41 - opencv 图片染色 及 移动
opencv 图片染色 及 移动前言一、图片的染色二、图片的移动1、图片移动的opencv库函数(warpAffine)参数解释2、实现3、效果及调用1、原图2、调用函数3、效果图前言 图像染色的原理很简单,首先指定一种渲染颜色,然后计算图片当前像…...
2024/4/20 13:52:41 - 小程序自定义分享好友和朋友圈
分享好友(一个小程序两个种登录类型) onShareAppMessage() {return {title: ,path: this.$public.hanldeDetailSharePath(this.material_id),imageUrl:}},getCurrentPages()[getCurrentPages().length-1].route 获取当前页面urlcache.getCache(login_ty…...
2024/4/24 19:22:47 - 现在什么牌子的蓝牙耳机比较好用呢?口碑最好的平价蓝牙耳机
不知道大家有没有注意到,现在几乎每个人在逛街或者坐地铁的时候都戴着无线耳机。这种耳机不仅是无线的,非常方便,而且还能降低噪音。在19年底,苹果降噪耳机的发布,彻底将我们带入了“降噪时代”。但实际上,…...
2024/4/20 13:52:39 - react-10(stateHook,effect Hook)
State Hook 1、16.8以后的新特性,现在可用 2、我们之前的组件都是以类的概念来实现的,里面可以 写函数、属性、state、视图,hook就是让我们在不写类的情况下也能实现效果,hook在类组件丽不生效。 (函数组件 ) 3、没有计划移除clas…...
2024/4/20 13:52:37 - 数据结构-时间复杂度和空间复杂度
文章目录一、算法效率复杂度二、时间复杂度大O的渐进表示法常见时间复杂度计算举例三、空间复杂度四、常见复杂度对比一、算法效率 什么是算法? 通常人们将算法定义为一个有穷的指令集,这些指令为解决某一特定任务规定了一个运算序列。 一个算法应具有以…...
2024/4/21 17:35:58 - UART接口与COM口的区别
嵌入式里面说的串口,一般是指UART口, 但是我们经常搞不清楚它和COM口的区别, 以及RS232, TTL等关系, 实际上UART,COM指的物理接口形式(硬件), 而TTL、RS-232是指的电平标准(电信号). UART有4个pin(VCC, GND, RX, TX), 用的TTL电…...
2024/4/21 17:35:57 - 实景三维术语总结
地理场景 一定区域范围内连续成片、反映现实世界地理空间位置和形态的地理信息数据。 地理实体 现实世界中占据一定且连续空间位置、单独具有同一属性或完整功能的地理对象,包括基础地理实体、部件三维模型以及其他实体。 基础地理实体 地理实体中作为统一空间定位…...
2024/4/21 17:35:57 - Kubernetes中的数据密集型工作负载:operator、工具需要标准化
从它诞生伊始,Kubernetes就展示了轻松处理无状态工作负载的能力——这些工作负载不需要与某种形式的永久存储数据交互。然而,随着时间的推移,这一开源容器编排引擎为处理数据库和其他持久数据源提供了钩子。 根据最近成立的Data on Kubernet…...
2024/4/21 17:35:56 - PWN-保护概述和溢出实例
0x00 检查保护情况 在编写漏洞利用代码的时候,需要特别注意目标进程是否开启了DEP(Linux下对应NX)、ASLR(Linux下对应PIE)等机制,例如存在DEP(NX)的话就不能直接执行堆栈上的数据,存在ASLR的话各个系统调用的地址就是随机化的 checksec rea…...
2024/4/21 17:35:54 - HT1622/HT1622G中英文资料
相信大家能够搜索到这篇文章,应该是遇到了急需数据调试方面的问题。我先简单介绍一下HT1622/HT1622G的功能: HT1622/HT1622G是一款常用的LCD驱动芯片 特性 工作电压:2.7 v ~ 5.2 v 内置的RC振荡器 1/4偏置,1/8占空比,帧频64Hz 最…...
2024/4/21 17:35:53
最新文章
- windows qt sdk 安装
在Windows上安装Qt SDK的步骤如下: 下载Qt SDK安装包: 打开Qt资源下载网站,如http://download.qt.io/。 选择适合您Windows版本和需求的Qt SDK版本进行下载。通常建议选择稳定版本,并确认是否包含所需的组件,如Qt Cre…...
2024/5/3 0:47:36 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 8卡微调Grok-1实战教程
本文是根据魔搭社区推出的轻量级训练推理工具SWIFT微调实战教程。SWIFT(Scalable lightWeight Infrastructure for Fine-Tuning)是一套基于PyTorch的轻量级、开箱即用的模型微调、推理框架,让AI爱好者能够轻松地在消费级显卡上运行大模型和AI…...
2024/5/2 21:55:42 - Ubuntu磁盘扩容
使用 df -h命令查看系统磁盘控件的使用情况: [samspobosrv:~]$ df -h Filesystem Size Used Avail Use% Mounted on udev 7.8G 0 7.8G 0% /dev tmpfs 1.6G 1.7M 1.…...
2024/5/2 12:55:10 - [Spring Cloud] gateway全局异常捕捉统一返回值
文章目录 处理转发失败的情况全局参数同一返回格式操作消息对象AjaxResult返回值状态描述对象AjaxStatus返回值枚举接口层StatusCode 全局异常处理器自定义通用异常定一个自定义异常覆盖默认的异常处理自定义异常处理工具 在上一篇章时我们有了一个简单的gateway网关 [Spring C…...
2024/5/1 13:04:53 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/1 17:30:59 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/2 16:16:39 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/29 2:29:43 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/2 9:28:15 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/27 17:58:04 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/27 14:22:49 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/28 1:28:33 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/30 9:43:09 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/27 17:59:30 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/2 15:04:34 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/28 1:34:08 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/26 19:03:37 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/29 20:46:55 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/30 22:21:04 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/1 4:32:01 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/4/27 23:24:42 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/28 5:48:52 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/30 9:42:22 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/2 9:07:46 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/30 9:42:49 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57