目录
StrictMode是什么
StrictMode从字面上翻译是严格模式的意思,它是Android提供的一种用来检测应用运行性能(耗时操作和内存泄漏等)的机制,它包含两大策略:线程策略(TreadPolicy)和 VM策略(VmPolicy)
ThreadPolicy线程策略:
自定义耗时检测:detectCustomSlowCalls()
磁盘读取耗时检测:detectDiskReads()
磁盘写入耗时检测:detectDiskWrites()
网络耗时检测:detectNetwork()
VmPolicy虚拟机策略:
Activity泄漏检测:detectActivityLeaks()
Closable对象泄漏检测:detectLeakedClosableObjects()
Sqlite对象检测:detectLeakedSqlLiteObjects()
实例数量检测:setClassInstanceLimit()
StrictMode怎么使用
StrictMode的使用方法非常简单,只需要在Application或者Activity中的onCreate()方法中加入如下代码即可:
public class MyApplication extends Application {
public static ArrayList<Activity> sLeakyActivities = new ArrayList<Activity>();
@Override
public void onCreate() {
//配置ThreadPolicy策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
//配置VmPolicy策略
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
super.onCreate();
}
}
当然如果对于ThreadPolicy策略你只想检测磁盘读的操作那么只需这样配置就行:
//配置ThreadPolicy策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.penaltyLog()
.build());
如果你想将所有的都进行检测那么你可以进行这样简写:
//配置ThreadPolicy策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()//检测所有
.penaltyLog()
.build());
我们已经将检测的代码写好了,接下来我们就可以通过运行APP然后就可以用Logcat或者adb命令查看检测到的问题了,这里为了展示的清晰我就对ThreadPolicy策略和VmPolicy策略分开来说了
ThreadPolicy策略
这里我在Application类中只设置ThreadPolicy
public class MyApplication extends Application {
public static ArrayList<Activity> sLeakyActivities = new ArrayList<Activity>();
@Override
public void onCreate() {
//配置ThreadPolicy策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()//检测磁盘写
.penaltyLog()
.build());
super.onCreate();
}
}
然后我们在MainActivity的主线中加入一段写入磁盘的操作:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"DiskWrite.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write("DiskWriteDiskWrite".getBytes());
fileOutputStream.flush();
fileOutputStream.close();
}catch (Exception e){
}
}
}
我们运行APP会发现Logcat打印出了如下信息:
我们可以看到Logcat中打印出了出现性能问题的具体位置,这时我们只需要找到并且修改为子线程处理即可:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
try {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"DiskWrite.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write("DiskWriteDiskWrite".getBytes());
fileOutputStream.flush();
fileOutputStream.close();
}catch (Exception e){
}
}
}).start();
}
}
当然我们也可以自定义一个检测如:
//MyApplication 中增加自定义检测的配置
public class MyApplication extends Application {
public static ArrayList<Activity> sLeakyActivities = new ArrayList<Activity>();
@Override
public void onCreate() {
//配置ThreadPolicy策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()//检测磁盘写
.detectCustomSlowCalls()//自定义检测
.penaltyLog()
.build());
super.onCreate();
}
}
//MainActivity 使用StrictMode.noteSlowCall()增加自定义检测
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//自定义检测
long start = System.currentTimeMillis();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background);
long useTime = System.currentTimeMillis() - start;
if(useTime > 3){
StrictMode.noteSlowCall("自定义耗时:" + useTime + "毫秒");
}
}
}
运行结果如下:
VmPolicy策略
这里我们先看一下Activity的内存泄漏的检测配置及效果:
public class MyApplication extends Application {
//用于保存Activity,以产生内存泄漏
public static ArrayList<Activity> LEAKY_ACTIVITIES = new ArrayList<Activity>();
@Override
public void onCreate() {
//配置VmPolicy策略
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectActivityLeaks()//Activity内存泄漏检测
.penaltyLog()
.build());
super.onCreate();
}
}
在MainActivity中加入一个按钮,点击后跳转LeaksActivity
public class MainActivity extends AppCompatActivity {
private Button btJump;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btJump = (Button) findViewById(R.id.bt_jump);
btJump.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,LeaksActivity.class));
}
});
}
}
在LeaksActivity中我们保存LeaksActivity的实例
public class LeaksActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaks);
MyApplication.LEAKY_ACTIVITIES.add(this);
}
}
然后我们运行APP,多点几次跳转按钮
我们可以在Logcat中看到,它告诉我们应该有一个实例而我们当前却有三个
另外我们也可以使用setClassInstanceLimit配置自定义的对象实例数量的检测,如下:
//配置VmPolicy策略
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectActivityLeaks()//Activity内存泄漏检测
.setClassInstanceLimit(TestUtil.class,1)//自定义的实例检测(超过1个了就提示)
.penaltyLog()
.build());
接下来我们再看看未关闭的Closable对象的检测,我们调整VmPolicy策略的配置如下
//配置VmPolicy策略
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectActivityLeaks()//Activity内存泄漏检测
.setClassInstanceLimit(TestUtil.class,1)//自定义的实例检测(超过1个了就提示)
.detectLeakedClosableObjects()//Closable对象未关闭检测
.penaltyLog()
.build());
然后在LeaksActivity 中添加一段子线程中写文件的操作,但是不给close
new Thread(new Runnable() {
@Override
public void run() {
try {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"closeable.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write("LeakedClosableObjects".getBytes());
fileOutputStream.flush();
}catch (Exception e){
}
}
}).start();
然后我们跳转到LeaksActivity 中然后返回会出现如下提示:
补充
这里我再说下如何使用adb shell查看StrictMode的信息
首先我们用adb shell 命令进入手机
然后使用如下命令:
logcat|grep StrictMode
然后如果有检测到性能问题的话就会出现跟Logcat一样的信息:
网友评论