8

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

@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:

这意味着,从磁盘读取以下内容: 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 规则。

问题

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

4

1 回答 1

16

Afaik,不存在从 StrictMode 配置中排除某些代码块(例如按包名称)的 API。实际上,我可以将 SharedPreferences 相关的内容留在 UI 线程上从磁盘读取。

它确实存在。StrictMode.allowThreadDiskReads()更改权限以允许读取并返回旧权限,以便在读取ThreadPolicy完成后可以将其重置。然后可以将其与“try-finally”设置一起使用,以允许读取单个操作。

val oldPolicy = StrictMode.allowThreadDiskReads()
try {
    // Do reads here
} finally {
    StrictMode.setThreadPolicy(oldPolicy)
}

您可以创建一个 kotlin 函数来使用 lambda 处理恢复:

fun <T> allowReads(block: () -> T): T {
    val oldPolicy = StrictMode.allowThreadDiskReads()
    try {
        return block()
    } finally {
        StrictMode.setThreadPolicy(oldPolicy)
    }
}
于 2018-04-15T15:29:31.383 回答