安卓 xml 文档 怎么xml打开方式式

AndroidManifest.xml文件详解(activity)(三)
android:launchMode
这个属性定义了应该如何启动Activity的一个指令。有四种工作模式会跟Intent对象中的Activity标记(FLAG_ACTIVITY_*常量)结合在一起用来决定被调用Activity在处理Intent对象时应该发生的事情,这四种模式是:
singleTask
singleInstance
默认的模式是standard。
像下表显示的那样,这四种模式被分成两组,standard和singleTop为一组,singleTask和singleInstance为一组。带有standard和singleTop启动模式的Activity能够被实例化多次。其实例能够属于任何任务,并且能够在Activity的堆栈中被定为。通常是调用startActivity()方法把它们加载到任务中(除非Intent对象包含了一个FLAG_ACTIVITY_NEW_TASK指令,这种情况下会选择启动一个新的任务。)
相比之下,singleTask和singleInstance启动模式的Activity只能启动一个任务。它们始终是Activity堆栈的根节点。并且设备每次只能拥有一个这样的Activity---只有一个这样的任务。
standard和singleTop模式彼此在一个方面有所不同:对于standard启动模式的Activity,每次要有一个新的Intent对象才能启动,会创建一个新的Activity类的实例来响应Intent对象的请求。每个实例处理一个Intent对象。同样,singleTop启动模式的Activity也会创建一个新的实例来处理一个新的Intent对象。但是,如果目标任务中在堆栈的顶部已经有了这个Activity的实例,那么这个实例会接受这个新的Intent对象(在onNewIntent()回调方法中调用);而不是创一个新的Activity实例。另一种情况,如:如果singleTop启动模式的Activity的一个实例,在目标任务中已经存在,但是它没有在任务堆栈的顶部,或者是在堆栈的顶部,却不是目标任务,那么就会创建一个新的Activity实例,并把它压入目标任务堆栈。
singleTask和singleInstance模式彼此也在一个方面有所不同:singleTask模式的Activity,允许其他Activity作为它所在任务的一部分。它始终在所在任务的根节点,但是其他的Activity(需要是standard和singleTop模式的Activity)能够被加载到它的任务中。而singleInstance模式的Activity,不允许其他的Activity做它所在任务的一部分。它是其任务中唯一的Activity。如果要启动另外的Activity,那么被启动的Activity要关联到不同的任务中---就像是在Intent对象中设置了FLAG_ACTIVITY_NEW_TASK标记一样。
支持多实例吗?
针对大多数Activity的启动模式
默认启动模式,系统总是在目标任务中创建一个新的Activity实例,并把Intent对象发送给它。
如果这中模式的Activity始终存在与目标任务堆栈的顶部,系统就会通过调用它的onNewIntent()方法,把Intent对象发送给这个实例,而不是创建一个的Activity实例。
特殊的启动模式,通常不推荐使用。
singleTask
系统在一个新任务堆栈的根节点处创建这个Activity,并且把Intent对象发送给它。但是,如果这个Activity的实例已经存在,系统就会通过调用它的onNewIntent()方法,把Intent对象发送给这个实例,而不是创建一个的Activity实例。
singleInstance
除了系统不能把其他的Activity加载到该Activity实例所归属的任务中之外,其他与singleTask模式相同。这种模式的Activity始终是单独存在的,并且是其任务中唯一的成员
如上表所示,standard模式是默认模式,并且适用于大多数Activity。singleTop也是一种通用的,且被很多Activity类型所使用的启动模式。其他模式(singleTask和singleInstance)是不推荐给大多数应用程序使用的,因为它们会产生用户不熟悉的交互模式,并且与大多数应用程序也会产生差异。
不管选择了那种启动模式,都要测试Activity在启动期间的可用性,并且在使用Back按钮时能够返回到其他的Activity和任务。
摘自 FireOfStar的专栏
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'eclipse android开发中在activity中引用别的xml控件id方法_蓝冰论坛
后使用快捷导航没有帐号?
只需一步,快速开始
只需一步,快速搞定
查看: 3083|回复: 6
eclipse android开发中在activity中引用别的xml控件id方法
主题帖子积分
我就拿TextView控件为例来演示:
LayoutInflater factorys = LayoutInflater.from(当前类.this);
final View textEntryView = factorys.inflate(R.layout.你要获取的另一个XML, null);
TextView lbhao = (TextView) textEntryView.findViewById(R.id.控件ID);
这样就引用了其他xml中的控件
主题帖子积分
正当我徜徉在丁字路口/徘徊在十字街头/迷茫丧志之时,读到了这则帖子。阅过,眼睛湿润/喉咙哽咽了。空前绝后无与伦比的经典之作啊 掩卷沉思 顿觉心里豁亮 茅塞顿开!犹如拿破仑流放琉璃岛读阅孙子兵法拍案惊奇:早得此卷 岂能败北。
主题帖子积分
路过帮帮顶顶!!
主题帖子积分
看完楼主的帖子,我的心情竟是久久不能平静。正如老子所云:大音希声,大象无形。我现在终于明白我缺乏的是什么了,正是楼主那种对真理的执着追求和楼主那种对理想的艰苦实践所产生的厚重感。面对楼主的帖子,我震惊得几乎不能动弹了,楼主那种裂纸欲出的大手笔,竟使我忍不住一次次地翻开楼主的帖子,每看一次,赞赏之情就激长数分,我总在想,是否有神灵活在它灵秀的外表下,以至能使人三月不知肉味,使人有余音绕梁、三日不绝的感受。楼主,你写得实在是太好了。我惟一能做的,就只有把这个帖子顶上去这件事了
主题帖子积分
抢个沙发, 积分 29, 距离下一级还需 171 积分
看完楼主的帖子,我的心情竟是久久不能平静。正如老子所云:大音希声,大象无形。我现在终于明白我缺乏的是什么了,正是楼主那种对真理的执着追求和楼主那种对理想的艰苦实践所产生的厚重感。面对楼主的帖子,我震惊得几乎不能动弹了,楼主那种裂纸欲出的大手笔,竟使我忍不住一次次地翻开楼主的帖子,每看一次,赞赏之情就激长数分,我总在想,是否有神灵活在它灵秀的外表下,以至能使人三月不知肉味,使人有余音绕梁、三日不绝的感受。楼主,你写得实在是太好了。我惟一能做的,就只有把这个帖子顶上去这件事了
主题帖子积分
主题帖子积分
谢谢楼主,共同发展
社区QQ达人
使用QQ帐号登录论坛的用户
该会员表现积极,特评价为最佳新人,大家鼓掌
该会员表现活跃积极,特评价为活跃会员,大家鼓掌
该会员热心乐于助人,特评价为热心会员,大家鼓掌
该会员推广神人,特评价为推广达人,大家鼓掌
该会员宣传可谓前无古人,特评价为宣传达人,大家鼓掌
该会员善于灌水,堪称绝灌,特评价为灌水之王,大家鼓掌
该会员有潜质,不解释,必成大器,特评价为突出贡献,大家鼓掌
该版主当的好,不多说,特评价为优秀版主,大家鼓掌
该会员有潜质,准备晋升管理员吧,特评价为荣誉管理,大家鼓掌
该会员,元老,你懂的,无所不知,特评价为论坛元老,大家鼓掌
技术讨论群:
技术讨论群:
工作时间:8:00-18:00Android相关信息
?相关Android文章推荐
热门Android文章推荐
横线渐变色 [html] ?xml version="
config_statusBarComponent" trans
首先设置只能输入数字: [html] Ed
SurfaceView 示波器的例子:直接上
最近做项目要用到IPHONE 左右滑动
属性名称 描述 android:columnWidt
在android应用程序中,有时要用到
阅读Android 4.0源码也有一段时间
废话少说,直接帖代码:如下-------
android4.0之前的菜单使用非常广泛
广告赞助商
Android文章阅读排
在AndroidManifest.xml文件中设置Android程序的启动界面方法(2)
摘要:!-- 设置最先启动的程序,要启动哪个Activity就把下面的代码复制到指定的位置 -- intent-filter action android:name=android.intent.action.MAIN / category android:name=android.intent.category.LAUNCHER / /int
&!-- 设置最先启动的程序,要启动哪个Activity就把下面的代码复制到指定的位置 --&
&intent-filter&
&action android:name=&android.intent.action.MAIN& /&
&category android:name=&android.intent.category.LAUNCHER& /&
&/intent-filter&
&/activity&
&/application&
&/manifest&
(原文出处:吾吾织梦)
------分隔线----------------------------
◎ 广告赞助
◎ 阅读说明READ EXPLANATION
推荐使用第三方专业下载工具下载本站软件,使用 WinRAR v3.10 以上版本解压本站软件。
下载本站资源,如果服务器暂不能下载请过一段时间重试!
如果遇到什么问题,请到本站论坛去咨寻,我们将在那里提供更多 、更好的资源!
本站提供的一些商业软件是供学习研究之用,如用于商业用途,请购买正版。下次自动登录
现在的位置:
& 综合 & 正文
android自动化测试中hierarchyviewer和uiautomatorviewer获取控件信息的方式比对(1)
android自动化测试中hierarchyviewer和uiautomatorviewer获取控件信息的方式比对(2)
android自动化新人一个,目前研究PC端获取android设备的控件信息有哪些方式。多多指教!
adroid的目录tools下有2个自带的工具hierarchyviewer和uiautomatorviewer,打开后,如下所示:
分别来介绍它们怎么使用的:
UiAutoMatorViewer
点击左上角的手机图样的小图标,出现弹出框,此时正在获取信息:
完成获取后得到了当前的手机界面:
然后你可以点击主面板中的图片,右面的属性面板会显示你所点击的区域的控件属性。(需要注意到是,你的手机设备或模拟器的api要在16以上,也就是android版本得是4.2以上,因为这个工具是google在4.2以后推出来的,只适用于4.2以后的版本)。
到这一步,我了解了如何使用这个工具,但是并不是我要研究的东西。我要知道他是如何和手机设备通信,然后获取控件信息的,所以我反编译了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
UiAutomatorM
RawImage rawI
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 =
File xmlDumpFile =
File screenshotFile =
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");
getUiHierarchyFile(device, xmlDumpFile, monitor);
} 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";
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);
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);
我原本以为这里面也应该有个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,在此感谢这个前辈,放出连接,新手同学可以研究下。
通过读这四篇,我对hierarchyviewer有了一定了解,对于这位前辈没给出的一些疑惑我做了一些深入的研究和总结。
1.hierarchyviewer是通过socket连接android设备的ViewServer,通过4939端口建立通信。
-s &device&
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 =
int currentDepth = -1;
while ((line = in.readLine()) != null) {
if ("DONE.".equalsIgnoreCase(line))
int depth = 0;
while (line.charAt(depth) == ' ')
while (depth &= currentDepth) {
if (currentNode != null)
currentNode = currentNode.
--currentD
currentNode = new ViewNode(window, currentNode, line.substring(depth));
currentDepth =
} catch (IOException e) {
Log.e("hierarchyviewer", "Error reading view hierarchy stream: " + e.getMessage());
if (currentNode == null)
while (currentNode.parent != null) {
currentNode = currentNode.
return currentN
通过标红的代码可知,创建ViewNode对象的时候,传入三个参数:window,currentNode,读取的行数据去掉空格后的line.找到ViewNode类。
package com.android.hierarchyviewerlib.
import java.util.ArrayL
import java.util.C
import java.util.HashM
import java.util.I
import java.util.L
import java.util.M
import java.util.S
import java.util.TreeS
import org.eclipse.swt.graphics.I
public class ViewNode
private static final double RED_THRESHOLD = 0.00004D;
private static final double YELLOW_THRESHOLD = 0.5D;
public static final String MISCELLANIOUS = "miscellaneous";
public String hashC
public List&Property& properties = new ArrayList();
public Map&String, Property& namedProperties = new HashMap();
public ViewN
public List&ViewNode& children = new ArrayList();
public int scrollX;
public int scrollY;
public int paddingL
public int paddingR
public int paddingT
public int paddingB
public int marginL
public int marginR
public int marginT
public int marginB
public boolean willNotD
public boolean hasM
public boolean hasF
public double measureT
public double layoutT
public double drawT
public ProfileRating measureRating = ProfileRating.NONE;
public ProfileRating layoutRating = ProfileRating.NONE;
public ProfileRating drawRating = ProfileRating.NONE;
public Set&String& categories = new TreeSet();
public int imageReferences = 1;
public int viewC
public int protocolV
public ViewNode(Window window, ViewNode parent, String data)
this.window =
this.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());
this.id = "unknown";
this.width = (this.height = 10);
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)
int start = 0;
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 +
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))
while (!(stop));
Collections.sort(this.properties, new Comparator(this)
public int compare(, ViewNode.Property destination) {
return pareTo(destination.name);
this.id = ((Property)this.namedProperties.get("mID")).
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", -) : getInt("layout:layout_leftMargin", -));
this.marginRight = ((this.namedProperties.containsKey("layout_rightMargin")) ? getInt("layout_rightMargin", -) : getInt("layout:layout_rightMargin", -));
this.marginTop = ((this.namedProperties.containsKey("layout_topMargin")) ? getInt("layout_topMargin", -) : getInt("layout:layout_topMargin", -));
this.marginBottom = ((this.namedProperties.containsKey("layout_bottomMargin")) ? getInt("layout_bottomMargin", -) : getInt("layout:layout_bottomMargin", -));
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 != -) && (this.marginRight != -) && (this.marginTop != -) && (this.marginBottom != -));
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) {
double totalMeasure = 0D;
double totalLayout = 0D;
double totalDraw = 0D;
for (int i = 0; i & N; ++i) {
child = (ViewNode)this.children.get(i);
totalMeasure += child.measureT
totalLayout += child.layoutT
totalDraw += child.drawT
for (i = 0; i & N; ++i) {
child = (ViewNode)this.children.get(i);
if (child.measureTime / totalMeasure &= 0.00004D)
child.measureRating = ProfileRating.RED;
else if (child.measureTime / totalMeasure &= 0.5D)
child.measureRating = ProfileRating.YELLOW;
child.measureRating = ProfileRating.GREEN;
if (child.layoutTime / totalLayout &= 0.00004D)
child.layoutRating = ProfileRating.RED;
else if (child.layoutTime / totalLayout &= 0.5D)
child.layoutRating = ProfileRating.YELLOW;
child.layoutRating = ProfileRating.GREEN;
if (child.drawTime / totalDraw &= 0.00004D)
child.drawRating = ProfileRating.RED;
else if (child.drawTime / totalDraw &= 0.5D)
child.drawRating = ProfileRating.YELLOW;
child.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.viewC
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)
return Boolean.parseBoolean(p.value);
} catch (NumberFormatException e) {
return defaultV
return defaultV
private int getInt(String name, int defaultValue) {
Property p = (Property)this.namedProperties.get(name);
if (p != null)
return Integer.parseInt(p.value);
} catch (NumberFormatException e) {
return defaultV
return defaultV
public String toString()
return this.name + "@" + this.hashC
public static class Property
public String toString()
return this.name + '=' + this.
public static enum ProfileRating
RED, YELLOW, GREEN, NONE;
在构造方法中,我了解到了它把传递过来的ViewNode对象作为当前对象的父对象,又把当前对象作为父节点的子节点。形成一个链表结构,这样我通过最上层的根节点就可以获得所有节点(佩服佩服,后悔自己数据结构和没学好啊!)。一行currentNode = new ViewNode(window, currentNode, line.substring(depth));解决了所有烦恼,就是理解的时候要花费一点时间。
通过源码的学习。我了解hierarchyviewer的工作方式,然后我动手用java自己来实现。下一篇再续讲,该吃饭了。
&&&&推荐文章:
【上篇】【下篇】}

我要回帖

更多关于 xml文件打开方式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信