我应该如何处理与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); }