android - 如何在改造中获得网络未连接和连接超时
问题描述
我想通过改造获得网络连接状态。
我用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")
}
}
}
}
}
解决方案
您应该始终对任何相关代码进行异常处理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")
}
要在 a 中显示错误,Toast
您可以使用您的LiveData
对象并在您的orAPIClientManager
中观察它Activity
Fragment
/* 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()
}
}
推荐阅读
- android - 注释处理器现在必须显式声明。- 黄油刀7.0.1.jar(黄油刀7.0.1.jar)
- java - 如何使用 java 10 的应用程序类数据共享功能?
- python - 在迁移文件中正确声明空的 Django PostgreSQL JSONField 默认值
- git - 如何以编程方式编辑旧的 git 提交消息?
- python - Flask-socketio - 未能设置“Access-Control-Allow-Origin”响应标头
- linux - 调用 mmap() 后 MAP_PRIVATE 如何处理对基础文件的更改
- ruby-on-rails - 无法使用 Devise 从 Rails 应用程序发送电子邮件
- html - 在 Web 应用程序中存储硬编码域名的最佳选择
- java - PDFBox - 将一个 pdf 拆分为多个 pdf 文件
- antlr4 - 为什么“点”规则匹配多个数字?