【问题标题】:How to catch the Exception in Retrofit android如何在 Retrofit android 中捕获异常
【发布时间】:2018-01-21 08:00:15
【问题描述】:
  1. 我已经定义了如下类。
  2. 我在这里使用了带有 Retrofit 的匕首

我想做的事::

我正在尝试在下面的请求中捕获OfflineException,如何在 Main Activity 中正确捕获它。


RequestInterceptor.java

public class RequestInterceptor implements Interceptor {

    ConnectivityManager connectivityManager;
    Application mApplication;

    @Inject
    public RequestInterceptor(Application mApplication) {
        this.mApplication = mApplication;
        connectivityManager = (ConnectivityManager) mApplication.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        if (isConnected()) {
            throw new OfflineException();
        }

        Request.Builder r = chain.request().newBuilder();
        return chain.proceed(r.build());
    }

    protected boolean isConnected() {
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        return networkInfo != null && networkInfo.isConnectedOrConnecting();
    }

    public class OfflineException extends IOException {

        @Override
        public String getMessage() {
            return mApplication.getResources().getString(R.string.app_no_connectivity);
        }

    }

}

NetModule.java

import android.app.Application;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.util.concurrent.TimeUnit;

import javax.inject.Singleton;

import commons.LinksAndKeys;
import dagger.Module;
import dagger.Provides;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import retrofitDagger.retrofitUtils.RequestInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


@Module
public class NetModule {

    String mBaseUrl;
    Application mApplication;

    // Constructor needs one parameter to instantiate.
    public NetModule(String baseUrl, Application application) {
        this.mBaseUrl = baseUrl;
        this.mApplication = application;
    }

    // Dagger will only look for methods annotated with @Provides
    @Provides
    @Singleton
    // Application reference must come from AppModule.class
    SharedPreferences providesSharedPreferences(Application application) {
        return PreferenceManager.getDefaultSharedPreferences(application);
    }

    @Provides
    @Singleton
    Application providesApplication() {
        return mApplication;
    }

    @Provides
    @Singleton
    Cache provideOkHttpCache(Application application) {
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        Cache cache = new Cache(application.getCacheDir(), cacheSize);
        return cache;
    }

    @Provides
    @Singleton
    Gson provideGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
        return gsonBuilder.create();
    }

    @Provides
    @Singleton
    OkHttpClient provideOkHttpClient(Cache cache) {
        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.cache(cache);
        client.addInterceptor(new  RequestInterceptor(mApplication));
        client.readTimeout(LinksAndKeys.READ_TIMEOUT, TimeUnit.SECONDS);
        client.connectTimeout(LinksAndKeys.CONNECTION_TIMEOUT, TimeUnit.SECONDS);
        return client.build();
    }

    @Provides
    @Singleton
    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(mBaseUrl)
                .client(okHttpClient)
                .build();
        return retrofit;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Inject
    Retrofit retrofit;
    TextView textView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ((App) getApplication()).getNetComponent().inject(this);

        //Create textview and findViewByID
        textView = (TextView) findViewById(R.id.textview_post);
        //Create a retrofit call object
        Call<List<Post>> posts = retrofit.create(Restapi.class).getPosts();

        //Enque the call
        posts.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
               //Set the response to the textview
                textView.setText(response.body().get(0).getBody());

            }

            @Override
            public void onFailure(Call<List<Post>> call, Throwable t) {
                //Set the error to the textview
                textView.setText(t.toString());
            }
        });
    }
}

【问题讨论】:

    标签: android retrofit okhttp dagger-2


    【解决方案1】:

    据我所知,没有互联网连接,RetrofitError 包含一个 ConnectionException 作为原因。

    public class RetrofitErrorHandler implements ErrorHandler {
    
        @Override
        public Throwable handleError(RetrofitError cause) {
            if (cause.isNetworkError()) {
                if (cause.getCause() instanceof SocketTimeoutException) {
                      /* your code here*/ 
                    return new MyConnectionTimeoutException();
                } else {
                    /* your code here*/
                    return new MyNoConnectionException();
                }
            } else {
                //Do whatever you want to do if there is not a network error.  
            }
        }
    }
    

    或者您可以创建一个自定义 Retrofit 客户端,在执行请求之前检查连接并引发异常。

    public class ConnectivityCheck implements Client {
    
        Logger log = LoggerFactory.getLogger(ConnectivityCheck.class);
    
        public ConnectivityCheck (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);
        }
    }
    

    然后在配置RestAdapter的时候使用

    RestAdapter.Builder().setEndpoint(serverHost)
                         .setClient(new ConnectivityCheck(new OkHttpClient(), ...))
    

    【讨论】:

      【解决方案2】:

      据我所知,我认为 Retrofit 不支持“在通话时检查连接”,我认为这不是您想要的。

      例如,尝试在通话前检查连接性,

      private void sendData() {
          if( isConnected ) {
                switch(call) {
                     case "userSignIn":
                            Call !
                            break;
                     ...
          }
      }
      

      也许你也可以查看solution

      【讨论】:

        猜你喜欢
        • 2013-09-20
        • 1970-01-01
        • 2011-04-03
        • 2021-03-26
        • 2013-09-04
        • 2021-05-23
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多