我有一个带有dagger设置的项目,使用以下提供程序方法:
@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
}
这是来自应用程序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()
}
在API 27模拟器上运行项目会导致以下行为:
使用以下日志:
D / StrictMode:StrictMode策略违规; 〜duration = 275 ms:android.os.StrictMode $ StrictModeDiskReadViolation:policy = 196671 violation = 2 在android.os.StrictMode $ AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1440) 在java.io.UnixFileSystem.checkAccess(UnixFileSystem.java:251) 在java.io.File.exists(File.java:807) 在android.app.ContextImpl.getDataDir(ContextImpl.java:2197) 在android.app.ContextImpl.getPreferencesDir(ContextImpl.java:517) 在android.app.ContextImpl.getSharedPreferencesPath(ContextImpl.java:714) 在android.app.ContextImpl.getSharedPreferences(ContextImpl.java:368) 在android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:167) 在android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:526) at com.some.package.di.module.AppModule $ Companion.provideSharedPreferences(AppModule.kt:112) ...
这意味着,following 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());
}
因为这会在UI线程上发生 - StrictModeDiskReadViolation
结果。
Afaik,不存在用于从StrictMode配置中排除一些代码块(例如,通过包名称)的API。实际上,我可以将SharedPreferences
相关内容留在UI线程上从磁盘读取。
由于这个问题,我不想关闭读/写StrictMode规则。
从这种情况中正常恢复的正确方法是什么?
答案 0 :(得分:5)
Afaik,不存在用于从StrictMode配置中排除一些代码块(例如,通过包名称)的API。实际上,我可以将与SharedPreferences相关的东西留在UI线程上从磁盘读取。
确实存在。 StrictMode.allowThreadDiskReads()
更改权限以允许读取并返回旧ThreadPolicy
,以便在读取完成后重置它。然后,这可以与“try-finally”设置一起使用,以允许读取单个操作。
val oldPolicy = StrictMode.allowThreadDiskReads()
try {
// Do reads here
} finally {
StrictMode.setThreadPolicy(oldPolicy)
}
您可以使用lambda创建一个kotlin函数来处理恢复:
fun <T> allowReads(block: () -> T): T {
val oldPolicy = StrictMode.allowThreadDiskReads()
try {
return block()
} finally {
StrictMode.setThreadPolicy(oldPolicy)
}
}