-->

Retrofit + Rxjava takes long time to invoke onErro

2020-07-13 06:16发布

问题:

I'm using Retrofit + Rxjava to get a list of entities from server, by my design when the task fails, first it checks Internet connection and after that it checks the connection to the server in doOnError method of Observable.

When Client is not connected to the Internet doOnError is invoked in a reasonable time and user get the error message but the problem is when Internet is connected and I get wrong port or domain (to check the server problem error) It takes a long time (about 1 min or longer) and it's really annoying. How can I reduce this time and what's the reason?

how I check Internet and Server connection :

public static boolean checkConnection(String ipOrUrl, int port) {
    try {
        int timeoutMs = 100;
        Socket socket = new Socket();
        SocketAddress soketAddress = new InetSocketAddress(ipOrUrl, port);
        socket.connect(soketAddress, timeoutMs);
        socket.close();
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

how I try to get list of entities :

    foodgetRetorfitService.getRestaurants()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
//here I'm checking the internet and server connection in the onlineTask if retrofit fail
//and if clients get Online this ( getRestaurantFromServer ) is called again.
            .doOnError(error -> {
                error.printStackTrace();
                NetworkUtils.doOnlineTask(new OnlineTask() {
                    public void doWhenOnline() {
                        getResturantsFromServer();
                    }
                }, true);
            })
            .subscribe(new Observer<List<Restaurant>>() {
                @Override
                public void onNext(List<Restaurant> restaurants) {
                    restaurantItemAdapter.updateAdapterData(restaurants);
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, "onError: rxjava and retrofit error : can't get restaurant list");
                    e.printStackTrace();
                }
            });

how doOnlineTask is Implemented

    public static void doOnlineTask(OnlineTask onlineTask, boolean autoRetry, int retryTimeout) {
        NetworkUtils.isOnline(autoRetry)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnError(error -> {
//here I check the Exception type ( I raised them when checking the connection )
                    if (error instanceof InternetConnectionException)
                        onlineTask.doWhenInternetFaild();

                    if (error instanceof ServerConnectionException)
                        onlineTask.doWhenServerFaild();
                })
                .retryWhen(t -> t.delay(2, TimeUnit.SECONDS))
                .subscribe(result -> {
                            if (result.equals(NetworkStatus.CONNECTED))
                                onlineTask.doWhenOnline();
                            else {
                                if (result.equals(NetworkStatus.INTERNET_FAILD))
                                    onlineTask.doWhenInternetFaild();
                                else if (result.equals(NetworkStatus.SERVER_FAILD))
                                    onlineTask.doWhenInternetFaild();
                            }
                        }, error -> error.printStackTrace()
                );
    }

onlineTask is just an abstract class

abstract public void doWhenOnline();

public void doWhenInternetFaild() {
   //implemented somehow
}


public void doWhenServerFaild() {
   //implemented somehow
}

What I tried :

I guessed it's timeout problem so I changed Retrofit timeout with OkHttpClient and It does not worked. also I changed timeouts set by myself and I reduced them. not working.

回答1:

I assume you are using OkHttp client to go with Retrofit. What you are looking for is most probably a connection timeout.

You can set different timeouts when building a client.

OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(15, TimeUnit.SECONDS)
                .build();