StrictMode对SharedPreferences的检查出来的IO操作
2024-10-09 17:03:27
在使用StrictMode时,发现会爆出
StrictMode policy violation;~duration=1949 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=23 violation=2
这个提示显示, 在UI线程中有IO操作,请这是尽量避免。
但是我们真的在UI线程中使用了吗?其实我们也是按照普通大众的方法调用的。 直接在UI线程中调用getSharedPreference方法,该方法可能就会产生IO操作。
跟着查一下源码吧.
在2.3版本中有这样的代码:
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
SharedPreferencesImpl sp;
File f = getSharedPrefsFile(name);
synchronized (sSharedPrefs) {
sp = sSharedPrefs.get(f);
if (sp != null && !sp.hasFileChanged()) {
//Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
return sp;
}
} FileInputStream str = null;
File backup = makeBackupFile(f);
if (backup.exists()) {
f.delete();
backup.renameTo(f);
} // Debugging
if (f.exists() && !f.canRead()) {
Log.w(TAG, "Attempt to read preferences file " + f + " without permission");
} Map map = null;
if (f.exists() && f.canRead()) {
try {
str = new FileInputStream(f);
map = XmlUtils.readMapXml(str);
str.close();
} catch (org.xmlpull.v1.XmlPullParserException e) {
Log.w(TAG, "getSharedPreferences", e);
} catch (FileNotFoundException e) {
Log.w(TAG, "getSharedPreferences", e);
} catch (IOException e) {
Log.w(TAG, "getSharedPreferences", e);
}
} synchronized (sSharedPrefs) {
if (sp != null) {
//Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
sp.replace(map);
} else {
sp = sSharedPrefs.get(f);
if (sp == null) {
sp = new SharedPreferencesImpl(f, mode, map);
sSharedPrefs.put(f, sp);
}
}
return sp;
}
}
看发生了xml的读写操作, 怪不得会有IO操作。
但是再4.0版本此处代码发生了变化。
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
SharedPreferencesImpl sp;
synchronized (ContextImpl.class) {
if (sSharedPrefs == null) {
sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>();
} final String packageName = getPackageName();
ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);
if (packagePrefs == null) {
packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
sSharedPrefs.put(packageName, packagePrefs);
} // At least one application in the world actually passes in a null
// name. This happened to work because when we generated the file name
// we would stringify it to "null.xml". Nice.
if (mPackageInfo.getApplicationInfo().targetSdkVersion <
Build.VERSION_CODES.KITKAT) {
if (name == null) {
name = "null";
}
} sp = packagePrefs.get(name);
if (sp == null) {
File prefsFile = getSharedPrefsFile(name);
sp = new SharedPreferencesImpl(prefsFile, mode);
packagePrefs.put(name, sp);
return sp;
}
}
if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
// If somebody else (some other process) changed the prefs
// file behind our back, we reload it. This has been the
// historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly();
}
return sp;
}
看代码,这里没看到XML的IO操作。 那这个IO跑哪里去了呢? 跟踪一下SharedPreferencesImpl的构造方法,
SharedPreferencesImpl(File file, int mode) {
mFile = file;
mBackupFile = makeBackupFile(file);
mMode = mode;
mLoaded = false;
mMap = null;
startLoadFromDisk();
} private void startLoadFromDisk() {
synchronized (this) {
mLoaded = false;
}
new Thread("SharedPreferencesImpl-load") {
public void run() {
synchronized (SharedPreferencesImpl.this) {
loadFromDiskLocked();
}
}
}.start();
}
你看, XML的读取确实启动新线程了,那为什么还要爆出IO操作呢? 重新跟踪堆栈,发现原来不是这段代码发生的IO操作,是在startReloadIfChangedUnexpectedly中发生的, 代码中有些, 处于多进程模式,或者targe版本较低版本都会走该方法。那该方法中就会有IO操作。
后面, 我又更改了targetAPI的版本,不会走到startReloadIfChangedUnexpectedly中去。 果然StrictMode不会再查出东西来了。
最新文章
- 在C#代码中应用Log4Net(四)在Winform和Web中捕获全局异常
- SQLServer数据库转换成MySQL数据库
- WinCE项目应用之虚拟仪器(VI)
- ArcGIS 设置地图显示范围大小(全屏显示)
- 图解 &; 深入浅出JavaWeb:事务必会必知
- delegate基于on
- js部分---函数与递归;
- POJ 3177 Redundant Paths(Tarjan)
- 关于解决 The processing instruction target matching ";[xX][mM][lL]"; is not allowed
- C++为QLabel增加单击事件
- 纯css 构造的tip
- PHP中的数据结构
- 【第十九篇】laydate设置起始时间,laydate设置开始时间和结束时间
- python中MySQLdb的使用
- JAVA二分搜索树
- teleport使用说明
- GoldenGate实时投递数据到大数据平台(1)-MongoDB
- 解决最近vs2017总是在加载工程的时候卡住不不动
- smartsvn学习(二)如何在Xcode下使用SVN
- HighCharts设置图表背景透明
热门文章
- DebugDiag收集Dump的使用说明
- 日期转换工具类 CommUtil.java
- azure 云上MySQL最新版本 MySQL5.7.11 批量自动化一键式安装 (转)
- linux创建git远程仓库
- Hibernate3.3用户手册摘要-1-辅助类,session
- Neutron GRE模式要注意的问题
- phpinfo详解
- Centos7和win7双系统调整默认启动
- [内核同步]自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- ORACLE Instant Client 配置