azi*_*ian 1 android disk-io kotlin android-sharedpreferences android-strictmode
我有一个带有匕首设置的项目,具有以下提供者方法:
@Module(...)
abstract class AppModule {
@Module
companion object {
...
@Provides
@Singleton
@JvmStatic
fun provideSharedPreferences(@AppContext context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
}
@Binds
@AppContext
@Singleton
abstract fun provideAppContext(application: Application): Context
}
Run Code Online (Sandbox Code Playgroud)
这是来自应用程序的代码onCreate():
override fun onCreate() {
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.penaltyDialog()
.build())
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build())
Timber.plant(Timber.DebugTree())
}
...
super.onCreate()
}
Run Code Online (Sandbox Code Playgroud)
在API 27模拟器上运行项目会导致以下行为:

使用以下日志:
D/StrictMode:StrictMode策略违规; 〜duration = 275 ms:android.os.StrictMode $ StrictModeDiskReadViolation:policy = 196671 violation = 2 at android.os.StrictMode $ AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1440)at java.io.UnixFileSystem.checkAccess(UnixFileSystem.java: 251)在java.io.File.exists(File.java:807)的android.app.ContextImpl.getDataDir(ContextImpl.java:2197)在Android上的android.app.ContextImpl.getPreferencesDir(ContextImpl.java:517).在Android.pretent.PreferenceManager.getDefaultSharedPreferences的android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:167)的android.app.ContextImpl.getSharedPreferences(ContextImpl.java:368)上的app.ContextImpl.getSharedPreferencesPath(ContextImpl.java:714) (PreferenceManager.java:526)com.some.package.di.module.AppModule $ Companion.provideSharedPreferences(AppModule.kt:112)...
这意味着,是下面 res.exists()从磁盘中读取:
if (!res.exists() && android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
Log.wtf(TAG, "Data directory doesn't exist for package " + getPackageName(),
new Throwable());
}
Run Code Online (Sandbox Code Playgroud)
因为这发生在UI线程上 - StrictModeDiskReadViolation结果.
Afaik,不存在用于从StrictMode配置中排除一些代码块(例如,通过包名称)的API.实际上,我可以将SharedPreferences相关内容留在UI线程上从磁盘读取.
我不想因为这个问题而关闭读/写StrictMode规则.
从这种情况中正常恢复的正确方法是什么?
Afaik,不存在用于从StrictMode配置中排除一些代码块(例如,通过包名称)的API.实际上,我可以将与SharedPreferences相关的东西留在UI线程的磁盘上读取.
它确实存在.StrictMode.allowThreadDiskReads()更改权限以允许读取并返回旧的权限,以便在读取ThreadPolicy完成后重置.然后,这可以与"try-finally"设置一起使用,以允许读取单个动作.
val oldPolicy = StrictMode.allowThreadDiskReads()
try {
// Do reads here
} finally {
StrictMode.setThreadPolicy(oldPolicy)
}
Run Code Online (Sandbox Code Playgroud)
您可以使用lambda创建一个kotlin函数来处理恢复:
fun <T> allowReads(block: () -> T): T {
val oldPolicy = StrictMode.allowThreadDiskReads()
try {
return block()
} finally {
StrictMode.setThreadPolicy(oldPolicy)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1622 次 |
| 最近记录: |