【问题标题】:How to get network not connected and connection timed out in retrofit如何在改造中获得网络未连接和连接超时
【发布时间】:2021-08-17 09:10:51
【问题描述】:

我想通过改造获得网络连接状态。

我使用CoroutineExceptionHandler 显示Toast,但它会得到Can't toast on a thread that has not called Looper.prepare()

如果我不使用CoroutineExceptionHandler,当网络未连接时它会崩溃并得到FATAL EXCEPTION: DefaultDispatcher-worker-1

如何获得网络未连接和连接超时状态?

这是我的代码,谢谢!

object APIClientManager {
    var tag: String = "APIClientManager"

    fun postMethod(_jsonObject: JSONObject, _parameters: JSONObject) {
        getResult(_jsonObject, _parameters)
    }

    fun getResult(_jsonObject: JSONObject, _parameters: JSONObject) {
        // set okHttpClient.
        val httpClient = OkHttpClient.Builder()
        httpClient.addInterceptor { chain ->
            val original = chain.request()

            val requestBuilder = original.newBuilder()
            requestBuilder
                .header("Content-Type", "application/json; charset=UTF-8")

            val request = requestBuilder.build()
            chain.proceed(request)
        }

        httpClient.connectTimeout(30, TimeUnit.SECONDS)
        httpClient.readTimeout(30, TimeUnit.SECONDS)

        val okHttpClient = httpClient.build()

        // Create Retrofit
        val retrofit = Retrofit.Builder()
            .baseUrl(GbApiSite)
            .client(okHttpClient)
            .build()

        // Create Service
        val service = retrofit.create(APIService::class.java)

        // Convert JSONObject to String
        val jsonObjectString = _jsonObject.toString()

        // Create RequestBody
        val requestBody = jsonObjectString.toRequestBody("application/json".toMediaTypeOrNull())

        val exceptionHandler = CoroutineExceptionHandler{_ , throwable->
            throwable.printStackTrace()
            // I want to show toast here but will get "Can't toast on a thread that has not called Looper.prepare()".
        }

        CoroutineScope(Dispatchers.IO + exceptionHandler).launch {
            // Do the POST request and get response
            val response = APIServiceFun(_parameters, service, requestBody).chooseFun()

            withContext(Dispatchers.Main) {
                if (response != null) {
                    if (response.isSuccessful) {
                        val gson = GsonBuilder().serializeNulls().create()
                        val json = gson.toJson(
                            JsonParser.parseString(
                                response.body()?.
                                string()
                            )
                        )

                        var returnJSONObj = JSONObject(json)

                        if(returnJSONObj.has("return_code")){
                            var returnCode = returnJSONObj.getString("return_code")

                            if(returnCode.compareTo("0") == 0){
                                if(returnJSONObj.has("return_msg"))
                                    APIServiceResult(returnJSONObj.getJSONObject("return_msg"), _parameters).chooseActivity()
                            }
                        }
                    } else
                        Log.e("retrofit error ", response.code().toString())
                } else {
                    Log.e(tag, "response is null")
                }
            }
        }
    }

}

【问题讨论】:

    标签: android kotlin retrofit


    【解决方案1】:

    您应该始终对任何与IO 相关的代码进行异常处理,因为它很可能会失败,这可以通过将您的网络调用代码包装在try catch 中轻松完成

    try{
        val response = APIServiceFun(_parameters, service, requestBody).chooseFun()
    }
    catch(e: SocketTimeoutException){
        Log.d("TAG", "Exception : $e")
    }
    catch(e: Exception){
        Log.d("TAG", "Exception : $e")
    }
    

    要在Toast 中显示错误,您可以在APIClientManager 中使用LiveData 对象并在ActivityFragment 中观察它

    /* In APIClientManager */
    val apiError: MutableLiveData<String> = MutableLiveData()
    
    // post error to this LiveData inside catch block as
    try{}
    catch(e: SocketTimeoutException){
        apiError.postValue("API call timed out, please try again")
    }
    catch(e: Exception){
        apiError.postValue("Network error occurred, please try again")
    }
    
    /* In Activity onCreate, observe the LiveData and show Toast when erro occurs */
    APIClientmanager.apiError.observe(this, Observer{
        if(!it.isNullOrEmpty){
            Toast.makeText(requireContext, it, Toast.LENGTH_LONG).show()
        }
    }
    

    【讨论】:

    • 我用你的方法获取状态,谢谢。但是我想在网络未连接时真正关闭'CoroutineScope',我该怎么办?
    猜你喜欢
    • 1970-01-01
    • 2017-10-06
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    相关资源
    最近更新 更多