####项目GitHub
本文要点
- 一般使用的卡顿优化工具
- 卡顿问题概述
- 卡顿问题分析难点
- 关于CPU Profiler
- 关于Systrace
- 关于StrictMode
- 磁盘读写违例检测实战
- 实例限制检测实战
#一般使用的卡顿优化工具
- CPU Profiler
- Systrace
- StrictMode (strict adj.精确的; 绝对的; 严格的,严谨的; [植]笔直的 mode n.方式; 状况; 时尚,风尚; 调式 模式;)
#卡顿问题概述
- 很多性能问题(如内存占用高、耗费流量等)都相对不容易被发现, 但是卡顿问题却是很容易被直观感受到的;
- 卡顿问题较难排查、定位;
#卡顿问题分析难点
- 可能的产生原因 繁杂:代码、内存、绘制、IO、【在主线程做UI处理、IO操作耗时操作】等;
- 线上卡顿问题,在线下难以复现, 卡顿问题跟用户届时的现场环境有很大的关系;
- 比如, 届时用户终端的磁盘IO空间不足,影响了APP的IO写入性能, 导致APP卡顿,这样的场景有时候是很难复现的; 【最好在问题发生时候,就记录下来用户届时的场景】
#关于CPU Profiler
-
图形的形式展示程序的执行时间、调用栈、执行次数等;
-
信息全面,包含了所有线程、所有方法的调用时间;
-
运行时开销比较严重,导致APP运行时所有函数都会不等比地变慢,可能会带偏优化方向;
-
使用方式
Debug.startMethodTracing();【在需要监控的代码块前添加(注意它有四个重载方法)】Debug.stopMethodTracing();【在需要监控的代码块后添加】- 生成的调试文件在sd卡:Android/data/packagename/files
- 上次在内存优化的实战中, 其实已经使用过,提到过CPU Profiler了, 这里可以看一下App内存优化 之 内存抖动解决实战!!!!!!
#关于Systrace
-
监控和
跟踪Api调用、线程运行情况,生成Html报告; -
需要在API 18以上使用,推荐TraceCompat;
-
使用方式
python systrace.py -t 10 [other-options][categories]- 可以参考CSDN某博客; 或Android性能优化 -- Systrace工具(有option或category的参数表格)
- 轻量级,开销小
- 直观反映CPU利用率
- 给出建议
#关于StrictMode
-
严苛模式,Android提供的一种运行时检测机制; 如果在开发阶段对成千上万行的代码进行code review, 可能效率是比较低下的; 使用StrictMode之后, 系统会
自动检测出来主线程当中违例的一些情况, 同时按照代码的配置给出相应的反应。 -
方便,强大,容易被忽视
-
主要检测:线程检测策略、虚拟机检测策略
- 线程检测策略【
StrictMode.setThreadPolicy()】: 如, 自定义的耗时调用检测,如detectCustomSlowCalls(); 磁盘读取操作检测,detectDiskReads()网络操作检测,detectNetwork()【detect vt.查明,发现; 洞察; 侦察,侦查; 】 - 虚拟机策略【
StrictMode.setVmPolicy()】: Activity泄漏检测,detectActivityLeaks()SqlLite对象泄漏检测,detectLeakedSqlLiteObjects()限制实例数量检测,setClassInstanceLimit(要限制的类实例,限制的数量)
- 线程检测策略【
-
具体使用: 可以在
Activity或者Application的onCreate()中调用StrictMode的方法:
private boolean DEV_MODE = true;
private void initStrictMode() {
if (DEV_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls() //API等级11,使用StrictMode.noteSlowCode
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()// or .detectAll() for all detectable problems
.penaltyLog() //在Logcat 中打印违规异常信息
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.setClassInstanceLimit(NewsItem.class, 1)
.detectLeakedClosableObjects() //API等级11
.penaltyLog()
.build());
}
}
-
【调试技巧】 设置一个
DEV_MODE标志位: 只有在线下开发的环境时将之设置为true,才会使进程打开StrictMode; -
【检测策略的调用】 detect开头的方法, 都是StrictMode提供的检测策略, 调用过了,则
StrictMode便会进行相应的检测和反应; -
【响应方式配置】
penaltyLog()【penalty n.惩罚,刑罚,害处】是出现违规后用log打印出来,即指定StrictMode的响应方式,StrictMode除了打印log的方式, 还有其他响应方式, 如penaltyDeath()可以让APP直接崩溃掉,penaltyDialog()可以弹出一个Dialog等!!!!!!!!! -
实战一下: 磁盘读写违例检测(
log的响应方式):
/**
* 模拟内存泄露的Activity
*/
public class MemoryLeakActivity extends AppCompatActivity implements CallBack{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_memoryleak);
ImageView imageView = findViewById(R.id.iv_memoryleak);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.splash);
imageView.setImageBitmap(bitmap);
CallBackManager.addCallBack(this);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.penaltyLog()
.build());
findViewById(R.id.iv_memoryleak).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
writeToExternalStorage();
}
});
}
/**
* 文件系统的操作
*/
public void writeToExternalStorage() {
try {
File externalStorage = Environment.getExternalStorageDirectory();
File mbFile = new File(externalStorage, "xxx.txt");
if (mbFile.exists()){
mbFile.createNewFile();
}
OutputStream output = new FileOutputStream(mbFile, true);
output.write("www.wooyun.org".getBytes());
output.flush();
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
CallBackManager.removeCallBack(this);
}
@Override
public void dpOperate() {
// do sth
}
}
Dialog的响应方式:
以上IO违例的原因就是
在主线程做了IO操作了, 这显然是不行的,需要开一个子线程给它整!
- 实例限制检测:
public class TestApp extends Application {
static MemoryLeakActivity i = new MemoryLeakActivity();
static MemoryLeakActivity j = new MemoryLeakActivity();
@Override
public void onCreate() {
super.onCreate();
//实例限制检测 测试
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.setClassInstanceLimit(MemoryLeakActivity.class, 1)
.detectLeakedClosableObjects() //API等级11
.penaltyLog()
.build());
}
}