java.lang.NullPointerException:尝试调用接口方法“java.lang.Object kotlinx.coroutines.flow.FlowCollector.emit”

And*_*rew 8 android nullpointerexception coroutine

一旦流发出第一个值,就会崩溃。

java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object kotlinx.coroutines.flow.FlowCollector.emit(java.lang.Object, kotlin.coroutines.Continuation)' on a null object reference
    at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$$inlined$collect$1.emit(Collect.kt:136)
    at com.happyfleet.app.data.UsbDataSource$mapResponse$$inlined$map$1$2.emit(Collect.kt:137)
    at com.happyfleet.app.data.UsbDataSource$mapResponse$$inlined$filter$1$2.emit(Collect.kt:137)
    at kotlinx.coroutines.flow.SharedFlowImpl.collect(SharedFlow.kt:351)
    at kotlinx.coroutines.flow.SharedFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
    at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:190)
    at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
    at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
    at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
    at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
    at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:328)
    at kotlinx.coroutines.flow.SharedFlowImpl.emitSuspend(SharedFlow.kt:472)
    at kotlinx.coroutines.flow.SharedFlowImpl.emit(SharedFlow.kt:374)
Run Code Online (Sandbox Code Playgroud)

我的视图模型代码:

@HiltViewModel
class ErrorActivityViewModel @Inject constructor(
    private val sendActivityReportUseCase: SendActivityReportUseCase,
    private val connectionRepository: ConnectionRepository
) : ViewModel() {

    fun sendActivityReport() = viewModelScope.launch {
        sendActivityReportUseCase.execute()
    }


    init {
        subscribeToSessionTime()
    }

    private fun subscribeToSessionTime() = viewModelScope.launch {
        val sessionTimeout = connectionRepository.getSessionTimeoutFlow()
        _sessionTimeoutFlow.emitAll(sessionTimeout)
    }

    private val _sessionTimeoutFlow = MutableSharedFlow<Int>()
    val sessionTimeoutFlow = _sessionTimeoutFlow.asSharedFlow()


    override fun onCleared() {
        super.onCleared()
        sendActivityReportUseCase.cancel()
    }
}
Run Code Online (Sandbox Code Playgroud)

And*_*rew 31

原因

sessionTimeout在分配 _sessionTimeoutFlow 值之前,流已连接到_sessionTimeoutFlowwith运算符。emitAll因为编译器是从上到下的。结果,firstinit在 _sessionTimeoutFlow 为 null 时被调用,然后 _sessionTimeoutFlow 在第 32 行获取其值。

解决方案

这里的顺序很重要。将流声明移至之前,init如图所示。

在此输入图像描述