How should I handle “No internet connection” with Retrofit on Android

前端 未结 8 893
一个人的身影
一个人的身影 2020-12-02 03:55

I\'d like to handle situations when there is no internet connection. Usually I\'d run:

ConnectivityManager cm =
    (ConnectivityManager)context.getSystemSer         


        
相关标签:
8条回答
  • 2020-12-02 04:57

    Here's what I did on API 29 & API 30:

    1. I created a simple WiFiService class that will hold the connectivityManager:

       class WifiService {
        private lateinit var wifiManager: WifiManager
        private lateinit var connectivityManager: ConnectivityManager
    
        companion object {
            val instance = WifiService()
        }
    
        fun initializeWithApplicationContext (context: Context) {
            wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
            connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        }
    
        // Helper that detects if online
        fun isOnline(): Boolean {
            val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
            if (capabilities != null) {
                when {
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> return true
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> return true
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> return true
                }
            }
            return false
          }
       }
    

    2. Create the ConnectivityInterceptor to check for internet access:

       class ConnectivityInterceptor: Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
            if (!WifiService.instance.isOnline()) {
                throw IOException("No internet connection")
            } else {
                return chain.proceed(chain.request())
            }
         }
       }
    

    3. Finally use it in Retrofit2 as follows:

       class RestApi {
        private val okHttpClient by lazy {
            OkHttpClient.Builder()
                .addInterceptor(ConnectivityInterceptor())
                .build()
        }
    
        // Define all the retrofit clients
        private val restApiClient by lazy {
            Retrofit.Builder()
                .baseUrl("http://localhost:10000")
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
         }
    
         // ...
       }
    
    0 讨论(0)
  • 2020-12-02 05:01

    With Retrofit 2, we use an OkHttp Interceptor implementation to check for network connectivity ahead of sending the request. If no network, throw an exception as appropriate.

    This allows one to specifically handle network connectivity issues before hitting Retrofit.

    import java.io.IOException;
    
    import okhttp3.Interceptor;
    import okhttp3.Response;
    import io.reactivex.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";
        }
    }
    
    0 讨论(0)
提交回复
热议问题