协程调用REST API-> FATAL EXCEPTION:main

时间:2019-10-01 07:50:10

标签: android kotlin kotlin-coroutines

我需要从REST API中获取一些数据,当我连接4G或wifi时一切正常,但是当我处于飞行模式时,应用程序崩溃,并显示以下错误:“ E / AndroidRuntime:FATAL EXCEPTION:main” < / p>

在获得日志之前(没有错误说:“跳过了1013帧!该应用程序可能在其主线程上做了太多工作。”)

所以我想在没有网络的情况下获取API会使应用程序崩溃,因为它在主线程中运行。但是我正在使用协程,对我来说,我做对了:

ViewModel

private val viewModelJob = SupervisorJob()
private val viewModelScope = CoroutineScope(viewModelJob + Dispatchers.Main)
init {
        viewModelScope.launch {
            videosRepository.refreshVideos()
        }
    }

存储库

suspend fun refreshVideos() {
        withContext(Dispatchers.IO) {
            val playlist = Network.devbytes.getPlaylist().await()
            //database.videoDao().insertAll(*playlist.asDatabaseModel())
        }
    }

服务

/**
 * A retrofit service to fetch a devbyte playlist.
 */
interface DevbyteService {
    @GET("devbytes.json")
    fun getPlaylist(): Deferred<NetworkVideoContainer>
}

/**
 * Build the Moshi object that Retrofit will be using, making sure to add the Kotlin adapter for
 * full Kotlin compatibility.
 */
private val moshi = Moshi.Builder()
        .add(KotlinJsonAdapterFactory())
        .build()

/**
 * Main entry point for network access. Call like `Network.devbytes.getPlaylist()`
 */
object Network {
    // Configure retrofit to parse JSON and use coroutines
    private val retrofit = Retrofit.Builder()
            .baseUrl("https://devbytes.udacity.com/")
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .build()

    val devbytes: DevbyteService = retrofit.create(DevbyteService::class.java)
}

所以完整的链条是:

ViewModel->具有Dispatchers.Main的协程

调用存储库->暂停函数,该函数使用Dispatchers.IO启动协程

通过对象网络调用Service->,我得到一个带有getPlaylist()的改造实例,该实例返回一个Deferred,并且对该方法的调用在存储库中带有await()

我在做什么错了?

2 个答案:

答案 0 :(得分:1)

您的API调用引发异常,因为没有网络连接(很可能是UnknownHostException)。

将其包装在try-catch中,并处理异常。

答案 1 :(得分:0)

CoroutineExceptionHandler可能是一种解决方案。 https://kotlinlang.org/docs/reference/coroutines/exception-handling.html#coroutineexceptionhandler

打开飞行模式时,进行网络呼叫的协程将引发异常。 就您而言,您可以执行以下操作。

    val handler = CoroutineExceptionHandler { _, exception -> 
            //Handle your exception
        }
    init {
        viewModelScope.launch(handler) {
            videosRepository.refreshVideos()
        }
    }