【问题标题】:StrictMode: StrictModeDiskReadViolation when creating SharedPreferenceStrictMode:创建 SharedPreference 时的 StrictModeDiskReadViolation
【发布时间】:2018-09-25 06:38:11
【问题描述】:

我有一个带有以下提供程序方法的匕首设置项目:

@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 毫秒:android.os.StrictMode$StrictModeDiskReadViolation:策略=196671 违规=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) 在 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 规则。

问题

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

【问题讨论】:

    标签: android kotlin android-sharedpreferences disk-io android-strictmode


    【解决方案1】:

    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)
        }
    }
    

    【讨论】:

    • 先生,这是正确的答案。感谢您的启发。对于其他读者,除了StrictMode.allowThreadDiskReads(),我还必须执行StrictMode.allowThreadDiskWrites()
    猜你喜欢
    • 1970-01-01
    • 2012-10-30
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多