通用解决方案:Android 性能优化工具篇:如何使用 DDMS 中的 TraceView 工
优采云 发布时间: 2022-10-26 17:52通用解决方案:Android 性能优化工具篇:如何使用 DDMS 中的 TraceView 工
前言
Traceview是手机应用性能分析定位过程中使用最多的工具;启动时间较长、界面切换时间过长时首选工具;如果勾选了接口的帧率,建议先将GPU配置文件以列表的形式显示在屏幕上,这样就可以先查出是否是帧率有问题这个界面再做后续调查
TraceView 定义
TraceView 是 Android 平台特有的数据采集 和分析工具。主要用于分析Android中应用的热点;TraceView本身只是一个数据分析工具,数据采集需要使用Android SDK。调试类或使用 DDMS 工具
两者的用法如下:
TraceView 是如何使用的
DDMS中TraceView的*敏*感*词*如下,调试器可以点击Devices中的应用,点击
按钮 Start Method Profiling 并单击 Stop Method Profiling
启用方法分析后,测试应用程序的目标页面。测试完成后,停止方法分析,界面会跳转到DDMS的trace分析界面。
如下所示:
TraceView界面比较复杂,它的UI分为两个面板,分别是Timeline Panel(时间线面板)和Profile Panel(分析面板);上图的上半部分是Timeline Panel(时间线面板),Timeline Panel也可以细分为左右Pane:
上图的下半部分是Profile Panel(分析面板)。Profile Panel是TraceView的核心界面,内涵非常丰富;主要展示一个线程中每个函数调用的情况(先在Timeline Panel中选择线程)。,包括CPU使用时间、调用次数等信息。而这些信息是寻找热点的关键依据
因此,对于开发者来说,一定要了解 Profile Panel 中每一列的含义;下表列出了 Profile Panel 中比较重要的列名和描述
TraceView 在行动
了解了 TraceView 的 UI 之后,就到了介绍如何使用 TraceView 查找热点的时候了。一般来说,热点包括两种类型的功能:
测试背景
APP在测试机上运行一段时间后,手机发热、死机、CPU占用率高。应用程序被切入后台监控CPU数据。结果表明,即使应用程序不执行任何操作,应用程序的 CPU 使用率也会不断增加。
TraceView结果界面显示后,进行数据分析。在 Profile Panel 中,选择 Cpu Time/Call 降序排序(从上到下排列,每一项的时间消耗从高到低),得到如图所示的结果:
验证码
大致可以判断是ImageLoaderTools$2.run()方法有问题。在下面找到这个方法来验证代码:
1 package com.sunzn.app.utils;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.lang.ref.SoftReference;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9
10 import android.content.Context;
11 import android.graphics.Bitmap;
12 import android.os.Environment;
13 import android.os.Handler;
14 import android.os.Message;
15
16 public class ImageLoaderTools {
17
18 private HttpTools httptool;
19
20 private Context mContext;
21
22 private boolean isLoop = true;
23
24 private HashMap mHashMap_caches;
25
26 private ArrayList maArrayList_taskQueue;
27
28 private Handler mHandler = new Handler() {
29 public void handleMessage(android.os.Message msg) {
30 ImageLoadTask loadTask = (ImageLoadTask) msg.obj;
31 loadTask.callback.imageloaded(loadTask.path, loadTask.bitmap);
32 };
33 };
34
35 private Thread mThread = new Thread() {
36
37 public void run() {
38
39 while (isLoop) {
40
41 while (maArrayList_taskQueue.size() > 0) {
42
43 try {
44 ImageLoadTask task = maArrayList_taskQueue.remove(0);
45
46 if (Constant.LOADPICTYPE == 1) {
47 byte[] bytes = httptool.getByte(task.path, null, HttpTools.METHOD_GET);
48 task.bitmap = BitMapTools.getBitmap(bytes, 40, 40);
49 } else if (Constant.LOADPICTYPE == 2) {
50 InputStream in = httptool.getStream(task.path, null, HttpTools.METHOD_GET);
51 task.bitmap = BitMapTools.getBitmap(in, 1);
52 }
53
54 if (task.bitmap != null) {
55 mHashMap_caches.put(task.path, new SoftReference(task.bitmap));
56 File dir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
57 if (!dir.exists()) {
58 dir.mkdirs();
59 }
60 String[] path = task.path.split("/");
61 String filename = path[path.length - 1];
62 File file = new File(dir, filename);
63 BitMapTools.saveBitmap(file.getAbsolutePath(), task.bitmap);
<p>
64 Message msg = Message.obtain();
65 msg.obj = task;
66 mHandler.sendMessage(msg);
67 }
68 } catch (IOException e) {
69 e.printStackTrace();
70 } catch (Exception e) {
71 e.printStackTrace();
72 }
73
74 synchronized (this) {
75 try {
76 wait();
77 } catch (InterruptedException e) {
78 e.printStackTrace();
79 }
80 }
81
82 }
83
84 }
85
86 };
87
88 };
89
90 public ImageLoaderTools(Context context) {
91 this.mContext = context;
92 httptool = new HttpTools(context);
93 mHashMap_caches = new HashMap();
94 maArrayList_taskQueue = new ArrayList();
95 mThread.start();
96 }
97
98 private class ImageLoadTask {
99 String path;
100 Bitmap bitmap;
101 Callback callback;
102 }
103
104 public interface Callback {
105 void imageloaded(String path, Bitmap bitmap);
106 }
107
108 public void quit() {
109 isLoop = false;
110 }
111
112 public Bitmap imageLoad(String path, Callback callback) {
113 Bitmap bitmap = null;
114 String[] path1 = path.split("/");
115 String filename = path1[path1.length - 1];
116
117 if (mHashMap_caches.containsKey(path)) {
118 bitmap = mHashMap_caches.get(path).get();
119 if (bitmap == null) {
120 mHashMap_caches.remove(path);
121 } else {
122 return bitmap;
123 }
124 }
125
126 File dir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
127
128 File file = new File(dir, filename);
129
130 bitmap = BitMapTools.getBitMap(file.getAbsolutePath());
131 if (bitmap != null) {
132 return bitmap;
133 }
134
135 ImageLoadTask task = new ImageLoadTask();
136 task.path = path;
137 task.callback = callback;
138 maArrayList_taskQueue.add(task);
139
140 synchronized (mThread) {
141 mThread.notify();
142 }
143
144 return null;
145 }
146
147 }
</p>
以上代码就是ImageLoaderTools图片工具类的全部代码。不急着研究这个类的代码实现过程。我们先看看这个类是怎么调用的:
1 ImageLoaderTools imageLoaderTools = imageLoaderTools = new ImageLoaderTools(this);
2
<p>
3 Bitmap bitmap = imageLoaderTools.imageLoad(picpath, new Callback() {
4
5 @Override
6 public void imageloaded(String picPath, Bitmap bitmap) {
7 if (bitmap == null) {
8 imageView.setImageResource(R.drawable.default);
9 } else {
10 imageView.setImageBitmap(bitmap);
11 }
12 }
13 });
14
15 if (bitmap == null) {
16 imageView.setImageResource(R.drawable.fengmianmoren);
17 } else {
18 imageView.setImageBitmap(bitmap);
19 }
</p>
调用 ImageLoaderTools 的过程非常简单:
在实例化ImageLoaderTools类的构造函数(第90-96行)的过程中,完成了网络工具HttpTools的初始化、新建图片缓存Map、创建下载队列、开启下载线程等工作。
这时候请注意开线程的操作。打开线程后,执行run()方法(35-88行)。此时isLoop的值为默认true,maArrayList_taskQueue.size()为0。在任务队列中maArrayList_taskQueue这个循环会一直持续到没有添加下载任务
在执行imageLoad()方法加载图片时,会先去缓存mHashMap_caches查看图片是否已经下载。如果已经下载,则直接返回对应的位图资源。如果没有找到,就会在maArrayList_taskQueue中添加一个下载任务,并唤醒对应的下载线程。之前打开的线程发现maArrayList_taskQueue.size() > 0后进入下载逻辑。下载任务完成后,将对应的图片资源添加到缓存mHashMap_caches,更新UI。下载线程执行挂起的wait()方法
一张图片下载的业务逻辑,这样就很容易理解了,好像也没什么问题。一开始我也是这么想的,但是后来在仔细分析代码的过程中发现,如果重新加载同一个图片资源,就会出现死循环
还记得缓存 mHashMap_caches 吗?
死循环才是手机发热、卡死、CPU占用率高的真正原因
解决方案
准确定位代码问题后,提出解决方案就很简单了。这里提供的解决方案是将wait()方法从内层while循环移到外层while循环,这样当同一张图片重复加载时就会死掉。线程一出现循环就挂起,这样就可以避免出现死循环。代码显示如下:
1 private Thread mThread = new Thread() {
2
3 public void run() {
4
5 while (isLoop) {
6
7 while (maArrayList_taskQueue.size() > 0) {
8
9 try {
10 ImageLoadTask task = maArrayList_taskQueue.remove(0);
11
12 if (Constant.LOADPICTYPE == 1) {
13 byte[] bytes = httptool.getByte(task.path, null, HttpTools.METHOD_GET);
14 task.bitmap = BitMapTools.getBitmap(bytes, 40, 40);
15 } else if (Constant.LOADPICTYPE == 2) {
16 InputStream in = httptool.getStream(task.path, null, HttpTools.METHOD_GET);
17 task.bitmap = BitMapTools.getBitmap(in, 1);
18 }
19
20 if (task.bitmap != null) {
21 mHashMap_caches.put(task.path, new SoftReference(task.bitmap));
22 File dir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
23 if (!dir.exists()) {
24 dir.mkdirs();
25 }
26 String[] path = task.path.split("/");
27 String filename = path[path.length - 1];
28 File file = new File(dir, filename);
29 BitMapTools.saveBitmap(file.getAbsolutePath(), task.bitmap);
30 Message msg = Message.obtain();
31 msg.obj = task;
32 mHandler.sendMessage(msg);
33 }
34 } catch (IOException e) {
35 e.printStackTrace();
36 } catch (Exception e) {
37 e.printStackTrace();
38 }
39
40 }
41
42 synchronized (this) {
43 try {
44 wait();
45 } catch (InterruptedException e) {
46 e.printStackTrace();
47 }
48 }
49
50 }
51
52 };
53
54 };
最后附上代码修改后运行的代码性能图,之前的执行已经重复了很多次。效率有了质的提升,手机过热、死机、CPU占用率高的现象也消失了。
总结
文章 中提到的功能只是列举了 TraceView 工具的部分用法。需要文中完整代码或者更多Android相关学习资料的可以这样做;点此查看获取方法或私信“Android进阶”,可以获得一系列Android技术学习手册;希望这本手册能给大家学习Android带来一些帮助
操作方法:网站TDK采集工具-网站的TDK设置方法
网站 的 TDK 是什么?TDK是网站的标题、描述和关键词(关键字),TDK是网站的一个很重要的元素,它是蜘蛛爬你的网站第一眼看到的之后,所以设置TDK对网站的优化很关键。如何设置 网站 的 TDK?今天给大家分享一个批处理行业的网站TDK采集工具,分析网站TDK的排名如何,从而更好的搭建自己的网站TDK ,详细参考下图
要做网站优化,首先要学会诊断网站问题,从基本的网站TDK(title,deion,keywords)到网站代码,框架,内部链接,外部链接、锚文本、404、301等。我们不应该说我们应该精通,至少我们应该知道什么可以做,什么不能做。
一个公司成立后网站,离不开网站的优化和推广。SEO优化是企业获得良好排名的有效手段。那么,企业网站的优化方案是什么?如何规划?
定位包括:用户群体定位、推广渠道定位、差异化定位、网站风格定位等,其中最重要的是用户群体定位和差异化定位。如果这两个定位正确,产品基本上就成功了一半。定位时,我们会使用思维导图模型来分析用户群有多大?商业模式解读!推广渠道示例!同行研究!我们将推导出商旅的差异化卖点。基于用户体验,我们将比同行做得更好。
了解我们的同行是网站规划中的重要一步。只有知己知彼,才能百战百胜。了解其网站物理结构、URL结构、关键词布局、现有收录和排名必须合理。
根据同行的定位和理解,核心关键词基本可以确定。关键词 的确定至关重要。core关键字是整个网站关键字系统的核心,不能容忍任何错误。一般来说,关键词也是难度和流量的关键词。
1. 频繁的站点TDK变更
一段时间后,SEO优化的朋友一般不会犯这样的错误。基本上,一些新手经常会犯这样的错误。频繁的网站标题改动危害很大,因为一个搜索引擎改动会再次被审查,增加了搜索引擎的解读成本,尤其是新的网站还在百度审核期,如果不被看好通过搜索引擎,百度很可能不会收录你的网站。所以如果你的 网站 不是很重要,不要只是改变标题。
2.关键词布局的选择不合理
众所周知,搜索引擎要求全站主要关键词的布局密度占全站内容的2%~8%。无论您选择什么关键词,密度都必须达到标准。其次,关键词的选择很重要。比如你是一个新站,你觉得你能做一个索引为5000的词吗?当然,这样的选择是不合理的,词语的选择需要根据自己的需要和实际情况。在选择关键词的时候,应该选择一些容易优化和用户关心的词。记住关键词不容易过热或过冷,过热容易优化,过冷不带来流量。此外,应避免使用 关键词。
网站优化没有统一的标准,更何况可以参考相同的案例,其中收录太多不确定因素,所以在网站优化的过程中,使用相同的方法两个不同的网站优化,结果可能会有所不同。虽然我们无法控制优化过程中的每一个因素,但通过一些更科学的方法,可以使优化结果朝着预定的方向发展。
一般来说,关于如何优化网站,我们建议你可以将网站的优化分成几个阶段,分阶段完成,这样可以让整个优化工作更加有序和快速。
如何优化网站:分析
在网站优化开始之前,应该详细分析市场和目标用户。否则,核心关键词和长尾关键词从何而来?网站的栏目和内容如何排列?在这个过程中不要仅仅依靠直觉。凭直觉选择的 关键词 通常最终会变得不可靠。当然,关键词 指数的分析在某些行业是不可靠的。正确的方法应该是整合各方数据,一般来自索引查询、关键词挖掘工具、搜索引擎下拉框、搜索引擎相关搜索、竞争对手网站等渠道,并将它们组合在一起。自己的能力和网站特性确定优化方案网站的方法和关键词。
如何优化网站:执行
没有必要引入过多的行政权力。我相信每个人都能明白真相。计划再好,也是一张废纸。