改造中如何让网络未连接和连接超时
How to get network not connected and connection timed out in retrofit
我想通过改造获得网络连接状态。
我用 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")
}
要在 Toast
中显示错误,您可以在 APIClientManager
中使用 LiveData
对象并在 Activity
或 Fragment
[ 中观察它=20=]
/* 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()
}
}
我想通过改造获得网络连接状态。
我用 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")
}
要在 Toast
中显示错误,您可以在 APIClientManager
中使用 LiveData
对象并在 Activity
或 Fragment
[ 中观察它=20=]
/* 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()
}
}