我应该如何处理与Android上的Retrofit“没有互联网连接”
如果没有互联网连接,我想处理情况。 通常我会运行:
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
(从这里 )发送请求到networking之前,并通知用户,如果没有互联网连接。
从我看到的改造不具体处理这种情况。 如果没有互联网连接,我只会因为超时而收到RetrofitError
。
如果我想将这种检查包含到每个HTTP请求中,那么我应该怎么做? 或者我应该这样做。
谢谢
亚历克斯
我最终做的是创build一个自定义的Retrofit客户端,在执行请求之前检查连通性并引发exception。
public class ConnectivityAwareUrlClient implements Client { Logger log = LoggerFactory.getLogger(ConnectivityAwareUrlClient.class); public ConnectivityAwareUrlClient(Client wrappedClient, NetworkConnectivityManager ncm) { this.wrappedClient = wrappedClient; this.ncm = ncm; } Client wrappedClient; private NetworkConnectivityManager ncm; @Override public Response execute(Request request) throws IOException { if (!ncm.isConnected()) { log.debug("No connectivity %s ", request); throw new NoConnectivityException("No connectivity"); } return wrappedClient.execute(request); } }
然后在configurationRestAdapter
时使用它
RestAdapter.Builder().setEndpoint(serverHost) .setClient(new ConnectivityAwareUrlClient(new OkHttpClient(), ...))
自1.8.0
改造以来,这已被弃用
retrofitError.isNetworkError()
你必须使用
if (retrofitError.getKind() == RetrofitError.Kind.NETWORK) { }
有多种types的错误可以处理:
NETWORK
与服务器通信时发生IOException,例如超时,无连接等。
CONVERSION
(de)序列化一个body时引发exception。
HTTP
从服务器收到非200 HTTP状态代码,例如502,503等等。
UNEXPECTED
尝试执行请求时发生内部错误。 重新抛出这个exception是最好的实践,所以你的应用程序崩溃了。
@AlexV你确定RetrofitError包含超时作为一个原因(当调用getCause()时,SocketTimeOutException)当没有互联网连接?
据我所知,当没有互联网连接RetrofitError包含一个ConnectionException作为原因。
如果你实现一个ErrorHandler,你可以这样做:
public class RetrofitErrorHandler implements ErrorHandler { @Override public Throwable handleError(RetrofitError cause) { if (cause.isNetworkError()) { if (cause.getCause() instanceof SocketTimeoutException) { return new MyConnectionTimeoutException(); } else { return new MyNoConnectionException(); } } else { [... do whatever you want if it's not a network error ...] } } }
使用Retrofit 2,我们使用OkHttp拦截器实现在发送请求之前检查networking连接。 如果没有networking,则适当引发exception。
这使得人们可以在进行改造之前专门处理networking连接问题。
import java.io.IOException; import okhttp3.Interceptor; import okhttp3.Response; import rx.Observable; public class ConnectivityInterceptor implements Interceptor { private boolean isNetworkActive; public ConnectivityInterceptor(Observable<Boolean> isNetworkActive) { isNetworkActive.subscribe( _isNetworkActive -> this.isNetworkActive = _isNetworkActive, _error -> Log.e("NetworkActive error " + _error.getMessage())); } @Override public Response intercept(Interceptor.Chain chain) throws IOException { if (!isNetworkActive) { throw new NoConnectivityException(); } else { Response response = chain.proceed(chain.request()); return response; } } } public class NoConnectivityException extends IOException { @Override public String getMessage() { return "No network available, please check your WiFi or Data connection"; } }
当您从http请求中收到Throwable
错误时,您可以使用如下方法检测networking错误:
String getErrorMessage(Throwable e) { RetrofitError retrofitError; if (e instanceof RetrofitError) { retrofitError = ((RetrofitError) e); if (retrofitError.getKind() == RetrofitError.Kind.NETWORK) { return "Network is down!"; } } }
更新 :我应该说,这只适用于改造1,而不是改造2。
你可以使用这个代码
Response.java
import com.google.gson.annotations.SerializedName; /** * Created by hackro on 19/01/17. */ public class Response { @SerializedName("status") public String status; public void setStatus(String status) { this.status = status; } public String getStatus() { return status; } @SuppressWarnings({"unused", "used by Retrofit"}) public Response() { } public Response(String status) { this.status = status; } }
NetworkError.java
import android.text.TextUtils; import com.google.gson.Gson; import java.io.IOException; import java.util.List; import java.util.Map; import retrofit2.adapter.rxjava.HttpException; import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; /** * Created by hackro on 19/01/17. */ public class NetworkError extends Throwable { public static final String DEFAULT_ERROR_MESSAGE = "Please try again."; public static final String NETWORK_ERROR_MESSAGE = "No Internet Connection!"; private static final String ERROR_MESSAGE_HEADER = "Error Message"; private final Throwable error; public NetworkError(Throwable e) { super(e); this.error = e; } public String getMessage() { return error.getMessage(); } public boolean isAuthFailure() { return error instanceof HttpException && ((HttpException) error).code() == HTTP_UNAUTHORIZED; } public boolean isResponseNull() { return error instanceof HttpException && ((HttpException) error).response() == null; } public String getAppErrorMessage() { if (this.error instanceof IOException) return NETWORK_ERROR_MESSAGE; if (!(this.error instanceof HttpException)) return DEFAULT_ERROR_MESSAGE; retrofit2.Response<?> response = ((HttpException) this.error).response(); if (response != null) { String status = getJsonStringFromResponse(response); if (!TextUtils.isEmpty(status)) return status; Map<String, List<String>> headers = response.headers().toMultimap(); if (headers.containsKey(ERROR_MESSAGE_HEADER)) return headers.get(ERROR_MESSAGE_HEADER).get(0); } return DEFAULT_ERROR_MESSAGE; } protected String getJsonStringFromResponse(final retrofit2.Response<?> response) { try { String jsonString = response.errorBody().string(); Response errorResponse = new Gson().fromJson(jsonString, Response.class); return errorResponse.status; } catch (Exception e) { return null; } } public Throwable getError() { return error; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NetworkError that = (NetworkError) o; return error != null ? error.equals(that.error) : that.error == null; } @Override public int hashCode() { return error != null ? error.hashCode() : 0; } }
在你的方法中实现
@Override public void onCompleted() { super.onCompleted(); } @Override public void onError(Throwable e) { super.onError(e); networkError.setError(e); Log.e("Error:",networkError.getAppErrorMessage()); } @Override public void onNext(Object obj) { super.onNext(obj); }
- 改造期望的BEGIN_OBJECT,但是BEGIN_ARRAY
- 如何重试HTTP请求与OkHttp / Retrofit?
- 无法在Android Retrofit库中为我的课程创build转换器
- Android Retrofit – onProgressUpdate显示进度通知
- 不支持的操作:Android,Retrofit,OkHttp。 在OkHttpClient中添加拦截器
- 改进 – 多部分请求:所需的MultipartFile参数“文件”不存在
- 如何获得响应作为string使用改造,而不使用GSON或Android中的任何其他库
- 在Android中使用Retrofit
- 改进callback获得响应正文