Android Kotlin协程在严格模式下崩溃

前端之家收集整理的这篇文章主要介绍了Android Kotlin协程在严格模式下崩溃 前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我在下面创建了一个非常简化的版本.
严格模式通过以下策略设置:

  1. StrictMode.setThreadPolicy(
  2. StrictMode.ThreadPolicy.Builder()
  3. .detectDiskReads()
  4. .detectDiskWrites()
  5. .detectNetwork() // or .detectAll() for all detectable problems
  6. .penaltyLog()
  7. .penaltyDeath()
  8. .build()
  9. )

视图模型只有一个函数,该函数调用时会使应用程序崩溃.该函数不执行任何操作(其主体为空)

  1. class Myviewmodel : viewmodel() {
  2. fun foo() {
  3. viewmodelScope.launch(Dispatchers.IO){ }
  4. }
  5. }

该活动在onCreate上调用viewmodel.foo(),从而使带有以下跟踪信息的应用程序崩溃.

  1. --------- beginning of crash
  2. 2019-04-08 22:07:49.579 1471-1471/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
  3. Process: com.example.myapplication,PID: 1471
  4. java.lang.RuntimeException: StrictMode ThreadPolicy violation
  5. at android.os.StrictMode$AndroidBlockGuardPolicy.onThreadPolicyViolation(StrictMode.java:1705)
  6. at android.os.StrictMode$AndroidBlockGuardPolicy.lambda$handleViolationWithTimingAttempt$0(StrictMode.java:1619)
  7. at android.os.-$$Lambda$StrictMode$AndroidBlockGuardPolicy$9nBulCQKaMajrWr41SB7f7YRT1I.run(Unknown Source:6)
  8. at android.os.Handler.handleCallback(Handler.java:873)
  9. at android.os.Handler.dispatchMessage(Handler.java:99)
  10. at android.os.Looper.loop(Looper.java:193)
  11. at android.app.ActivityThread.main(ActivityThread.java:6669)
  12. at java.lang.reflect.Method.invoke(Native Method)
  13. at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
  14. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
  15. Caused by: android.os.strictmode.DiskReadViolation
  16. at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1504)
  17. at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:241)
  18. at java.io.File.isDirectory(File.java:845)
  19. at dalvik.system.DexPathList$Element.maybeInit(DexPathList.java:696)
  20. at dalvik.system.DexPathList$Element.findResource(DexPathList.java:729)
  21. at dalvik.system.DexPathList.findResources(DexPathList.java:526)
  22. at dalvik.system.BaseDexClassLoader.findResources(BaseDexClassLoader.java:174)
  23. at java.lang.ClassLoader.getResources(ClassLoader.java:839)
  24. at java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:349)
  25. at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:402)
  26. at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:488)
  27. at kotlin.collections.CollectionsKt___CollectionsKt.toCollection(_Collections.kt:1145)
  28. at kotlin.collections.CollectionsKt___CollectionsKt.toMutableList(_Collections.kt:1178)
  29. at kotlin.collections.CollectionsKt___CollectionsKt.toList(_Collections.kt:1169)
  30. at kotlinx.coroutines.internal.MainDispatcherLoader.loadMainDispatcher(MainDispatchers.kt:15)
  31. at kotlinx.coroutines.internal.MainDispatcherLoader.<clinit>(MainDispatchers.kt:10)
  32. at kotlinx.coroutines.Dispatchers.getMain(Dispatchers.kt:55)
  33. at androidx.lifecycle.viewmodelKt.getviewmodelScope(viewmodel.kt:41)
  34. at com.example.myapplication.Myviewmodel.foo(MainActivity.kt:35)
  35. at com.example.myapplication.MainActivity.onCreate(MainActivity.kt:28)
  36. at android.app.Activity.performCreate(Activity.java:7136)
  37. at android.app.Activity.performCreate(Activity.java:7127)
  38. at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
  39. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
  40. at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
  41. at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
  42. at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
  43. at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
  44. at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
  45. at android.os.Handler.dispatchMessage(Handler.java:106)
  46. at android.os.Looper.loop(Looper.java:193) 
  47. at android.app.ActivityThread.main(ActivityThread.java:6669) 
  48. at java.lang.reflect.Method.invoke(Native Method) 
  49. at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
  50. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

根据堆栈跟踪,有磁盘读取冲突,但是该代码中的任何内容都不应访问磁盘.
感兴趣的行是:

  1. at com.example.myapplication.Myviewmodel.foo(MainActivity.kt:35)
  2. at com.example.myapplication.MainActivity.onCreate(MainActivity.kt:28)

第35行:viewmodelScope.launch(Dispatchers.IO){}

第28行:viewmodel.foo()

更进一步,如果我删除了刑罚日志(),则应用程序不会崩溃.

所以我的问题是:

如何使用上述严格模式配置防止崩溃?

协程或严格模式本身存在问题吗?

更新:
这似乎是协程的一个已知问题.仍未解决-查看对话here

最佳答案
解决方案是使用您自己初始化的调度程序,而不在主线程上执行I / O.

实施起来有点棘手,因为要避免由于默认情况下在Handler上启用了vsync(可能会延迟多达16ms的代码,根本不需要vsync)而导致应用程序变慢,则必须使用API​​ 28构造函数,并使用反映旧版本的Android.之后,您可以对Handler使用asCoroutineDispatcher()扩展函数,并使用生成的调度程序.

为了使它对我和其他人更简单,我制作了一个(小)库,该库提供了Dispatchers.MainAndroid扩展,它无需任何I / O即可延迟初始化,并且可以代替Dispatchers.Main使用.它还将生命周期与协同程序范围集成在一起.

在这里,您可以查看如何获取依赖关系(在jcenter上可用)以及如何实现依赖关系:https://github.com/LouisCAD/Splitties/tree/master/modules/lifecycle-coroutines

猜你在找的Android相关文章