StrictMode 严格模式
开发者经常会无意地犯些错误:在主线程读写磁盘、访问网络,严格模式能够把帮助开发者监控这些错误。
注意:严格模式是一种保护机制但是并不保证找出所有的磁盘和网络访问。因为严格模式经常在发生Binder Call的时候报告自己的状态,所以它是一种尽力而为的机制。一般地,网络和磁盘访问一般走JNI调用,所以不一定会触发它。还有一点,线上的应用不应该开启严格模式。
代码示例:
public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate();
}
严格模式下的两种策略
StrictMode.ThreadPolicy(作用于特定线程)
主要监控以下内容:
Disk Reads 磁盘读
Disk Writes 磁盘写
Network access 网络访问
Custom Slow Code 自定义的运行速度慢的代码分析
StrictMode.VmPolicy(作用于整个虚拟机进程的所有线程)
主要监控以下内容:
内存泄露的Activity对象
内存泄露的SQLite对象
内存泄露的释放的对象
内存泄漏的BroadcastReceiver or ServiceConnection
严格模式监控到异常信息触发的提示
Log 日志
Death 应用退出
DropBox 持久化的、系统级别的Logcat
测试
代码
package com.jinglong.strickmodetest;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
public static final String STRICK_MODE_TEST = "StrickModeTest";
public static final String TAG = STRICK_MODE_TEST + ":" +MainActivity.class.getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
File externalStorageDirectory = Environment.getExternalStorageDirectory();
if (externalStorageDirectory==null||!externalStorageDirectory.exists()){
Log.d(TAG,"SDCard is not exist");
}else{
//获取SD卡下的文件或目录
String[] childrenFiles = externalStorageDirectory.list();
for (int i = 0;i < childrenFiles.length;i++){
File childFile = new File(externalStorageDirectory.getPath(),childrenFiles[i]);
if (childFile.exists()&&childFile.isFile()){
//找到第一个File
try {
FileReader fr = new FileReader(childFile);
char ch[] = new char[1024] ;
while (fr.read(ch)!=-1){
Log.e(TAG,new String(ch));
}
//为了测试效果,此处不关fr
FileWriter fw = new FileWriter(childFile);
fw.write("Hello 璟龙");
fw.flush();
//为了测试效果,此处不关fw
break;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
日志
- 第一条日志表示资源没有关闭,即IO流未关闭
- 第二条日志表示在主线程中发生了磁盘访问的读操作
07-18 15:05:26.930 10735-10748/com.jinglong.strickmodetest E/StrictMode: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
07-18 15:05:26.949 10735-10735/com.jinglong.strickmodetest D/StrictMode: StrictMode policy violation; ~duration=44 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=31 violation=2