我已经创建了一个非常简化的问题版本,如下所示。
以下是设置严格模式的策略:
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.penaltyDeath()
.build()
)
视图模型只有一个函数,调用该函数会导致应用程序崩溃。该函数什么也不做(它的主体为空)。
class MyViewModel : ViewModel() {
fun foo() {
viewModelScope.launch(Dispatchers.IO){ }
}
}
在onCreate
中调用viewModel.foo()
,导致应用程序崩溃,并显示以下跟踪信息。
--------- beginning of crash
2019-04-08 22:07:49.579 1471-1471/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 1471
java.lang.RuntimeException: StrictMode ThreadPolicy violation
at android.os.StrictMode$AndroidBlockGuardPolicy.onThreadPolicyViolation(StrictMode.java:1705)
at android.os.StrictMode$AndroidBlockGuardPolicy.lambda$handleViolationWithTimingAttempt$0(StrictMode.java:1619)
at android.os.-$$Lambda$StrictMode$AndroidBlockGuardPolicy$9nBulCQKaMajrWr41SB7f7YRT1I.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: android.os.strictmode.DiskReadViolation
at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1504)
at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:241)
at java.io.File.isDirectory(File.java:845)
at dalvik.system.DexPathList$Element.maybeInit(DexPathList.java:696)
at dalvik.system.DexPathList$Element.findResource(DexPathList.java:729)
at dalvik.system.DexPathList.findResources(DexPathList.java:526)
at dalvik.system.BaseDexClassLoader.findResources(BaseDexClassLoader.java:174)
at java.lang.ClassLoader.getResources(ClassLoader.java:839)
at java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:349)
at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:402)
at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:488)
at kotlin.collections.CollectionsKt___CollectionsKt.toCollection(_Collections.kt:1145)
at kotlin.collections.CollectionsKt___CollectionsKt.toMutableList(_Collections.kt:1178)
at kotlin.collections.CollectionsKt___CollectionsKt.toList(_Collections.kt:1169)
at kotlinx.coroutines.internal.MainDispatcherLoader.loadMainDispatcher(MainDispatchers.kt:15)
at kotlinx.coroutines.internal.MainDispatcherLoader.<clinit>(MainDispatchers.kt:10)
at kotlinx.coroutines.Dispatchers.getMain(Dispatchers.kt:55)
at androidx.lifecycle.ViewModelKt.getViewModelScope(ViewModel.kt:41)
at com.example.myapplication.MyViewModel.foo(MainActivity.kt:35)
at com.example.myapplication.MainActivity.onCreate(MainActivity.kt:28)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
根据堆栈跟踪,存在磁盘读取违规,但是那段代码中没有任何内容应该访问磁盘。
感兴趣的代码行为:
at com.example.myapplication.MyViewModel.foo(MainActivity.kt:35)
at com.example.myapplication.MainActivity.onCreate(MainActivity.kt:28)
第35行:viewModelScope.launch(Dispatchers.IO){ }
第28行:viewModel.foo()
此外,如果我删除penaltyLog()
,应用程序就不会崩溃。
我的问题是:
如何使用上述严格模式配置避免崩溃?
问题出在协程还是严格模式本身?
更新:这似乎是协程的已知问题。仍未解决 - 请参见此处的讨论
Dispatchers.MAIN
,它是否仍会崩溃? - Jeel Vankhede