StrictMode:创建SharedPreference时的StrictModeDiskReadViolation

StrictMode: StrictModeDiskReadViolation when creating SharedPreference

我有一个使用以下提供程序方法设置 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 policy violation; ~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) at java.io.File.exists(File.java:807) at android.app.ContextImpl.getDataDir(ContextImpl.java:2197) at android.app.ContextImpl.getPreferencesDir(ContextImpl.java:517) at android.app.ContextImpl.getSharedPreferencesPath(ContextImpl.java:714) at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:368) at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:167) at 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,不存在 API 从 StrictMode 配置中排除一些代码块(例如,通过包名称)。实际上,我可以将 SharedPreferences 相关内容留在 UI 线程上从磁盘读取。

因为这个问题,我不想关闭 read/write StrictMode 规则。

问题

从这种情况中正常恢复的正确方法是什么?

Afaik, there does not exist an API to exclude some chunk of code (e.g. by package name) from StrictMode configuration. Practically, I'm ok to leave SharedPreferences related stuff to read from disk on UI thread.

确实存在。 StrictMode.allowThreadDiskReads() 更改权限以允许读取,returns 旧的 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)
    }
}