好看的响应式网站,怎样做下载网站,中企动力做的 石子厂网站,医疗门户网站管理系统8种机械键盘轴体对比本人程序员#xff0c;要买一个写代码的键盘#xff0c;请问红轴和茶轴怎么选#xff1f;背景项目中使用了鸿洋大神的TreeView树状结构控件#xff0c; 但是由于在主线程中使用了注解/反射来定位节点#xff0c; 内容一多就有点卡顿。因此通过android …8种机械键盘轴体对比本人程序员要买一个写代码的键盘请问红轴和茶轴怎么选背景项目中使用了鸿洋大神的TreeView树状结构控件 但是由于在主线程中使用了注解/反射来定位节点 内容一多就有点卡顿。因此通过android device monitor中的性能分析工具定位并优化这一问题并记录过程。准备工作打开tools菜单 —— android——android device monitor选中要追踪的app进程——点击Start Method Profiling操作想要追踪问题的界面或行为使问题暴露在刚才的按钮点击stop分析卡顿根本原因由于Ui渲染被阻塞造成它运行在主线程 因此主线程也被称为UI线程。原因可能有很多常见的有主线程中执行速度较慢的I/O操作造成CPU等待 或主线程有其他大量任务占满了CPU 比如程序没写好死循环了 - - 。那么我们在这边主线程没有做I/O操作 因此先按 Excl Cpu Time % 排序 查看CPU占用百分比 。定位到 no.18 的方法占用了30.4% 点选他之后 看到 【1】main 主线程中后面大部分都变色 表明是这个method的执行区间。 卡顿罪魁祸首就是它了点开方法名左边小箭头 parent表示是被哪个父方法调用 children是表示调用的所有子方法。点开children分析后面几个参数Incl Cpu Time 表示各子方法的总运行时长, 主要就看他定位具体方法Incl Cpu Time % 就是各子方法的分配到的CPU占比callsRecurCalls/Total 表示被调用的次数 (大致符合逻辑就行 主要是看不是异常大 判断死循环)找到性能表现有问题的方法后一个一个双击看下去就可以了, 同时结合上半部分界面的运行时图表也能直观看出资源占用的区间优化看一下排前5的几个方法, 2个属于反射获取Annotation和Filed, 反射是众所周知的慢, 先放过他们, 另外3个我们看一下方法内容/*** 将我们的数据转化为树的节点** param datas** return** throws NoSuchFieldException* throws IllegalAccessException* throws IllegalArgumentException*/private static List convetData2Node(List datas)throws IllegalArgumentException, IllegalAccessException{List nodes new ArrayList();Node node null;for (T t : datas) {int id -1;int pId -1;int pnode -1;String label null;Class extends Object clazz t.getClass();Field[] declaredFields clazz.getDeclaredFields();for (Field f : declaredFields) {if (f.getAnnotation(TreeNode.class) ! null) {f.setAccessible(true);pnode f.getInt(t);}if (f.getAnnotation(TreeNodeId.class) ! null) {f.setAccessible(true);id f.getInt(t);}if (f.getAnnotation(TreeNodePid.class) ! null) {f.setAccessible(true);pId f.getInt(t);}if (f.getAnnotation(TreeNodeLabel.class) ! null) {f.setAccessible(true);label (String) f.get(t);}if (pnode ! -1 id ! -1 pId ! -1 label ! null) {break;}}node new Node(pnode, id, pId, label);nodes.add(node);}/** 设置Node间父子关系;让每两个节点都比较一次即可设置其中的关系*/for (int i 0; i nodes.size(); i) {Node n nodes.get(i);for (int j i 1; j nodes.size(); j) {Node m nodes.get(j);if (m.getpId() n.getId()) {n.getChildren().add(m);m.setParent(n);} else if (m.getId() n.getpId()) {m.getChildren().add(n);n.setParent(m);}}}// 设置图片for (Node n : nodes) {setNodeIcon(n);}return nodes;}反射创建节点后通过for循环设置节点的上下级关系 就是这个for循环有问题了。getId和getPid方法鸿洋大神的Node类是个标准javaBean 也就是属性全部private通过get, set操作。but 这样会比直接读属性慢10倍左右 其实也没啥大不了 but 如果被调用很多次。。。我把 id 和 pid 改成public 并删掉 get set方法ArrayList.size()这个也很简单直接在for循环里定义下变量。改完后的for循环如下/** 设置Node间父子关系;让每两个节点都比较一次即可设置其中的关系*/for (int i 0, a nodes.size(); i a; i) {Node n nodes.get(i);for (int j i 1; j a; j) {Node m nodes.get(j);if (m.pId n.id) {n.getChildren().add(m);m.setParent(n);} else if (m.id n.pId) {m.getChildren().add(n);n.setParent(m);}}}效果如下图 虽然cpu%提高了但那是由于其他耗时方法不见了因此总占比就高了具体看children分类下面那3个耗时较长的方法已经不见了self分类的时间也有所降低。 因此incl Cpu Time从2938降低到了1096毫秒效果还是比较显著的虽然方法优化完了但还是有1秒的卡顿存在 因此我后来又改了下把转换节点的操作放到子线程执行了这就不详细讲了。总结使用Android Device Monitor工具 捕获问题发生时的方法执行信息按Excl Cpu Time % 排序 找到需要优化的方法查看方法的children列表 分析Incl Cpu Time 和 callsRecurCalls/Total是否合理找到并修改方法再次捕获信息 对比分析