为什么在没有网络连接的情况下改装客户端会崩溃?

时间:2017-03-31 12:09:21

标签: java android crash retrofit2 rx-java2

在我的Android应用程序中,我使用Retrofit 2.2和RxJava 2进行网络调用。当设备连接到网络时,一切都很好。 当我禁用移动和WiFi网络时,应用程序崩溃。 奇怪的是我可以正确处理错误但是应用程序仍然会崩溃。

这是Retrofit的API接口:

public interface BackendApi {

 @GET("v1/users/{uuid}")
 Observable<User> getUser(@Path("uuid") String userUuid);

}

以下方法返回一个Observable,它将在我的视图模型中订阅。

@Override
public Observable<User> getUser(@NonNull final UUID id) {
    return api.getUser(id.toString()).map(user -> mapUser(user));
}

在视图模型中,我订阅了Observable:

compositeDisposable.add(userService.getUser(userId)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onGetUser, this::onGetUserError));

以下行显示了错误处理方法

 private void onGetUserError(final Throwable throwable) {
    log.error("onGetUserError, getting user failed because of {}", 
 throwable.getCause());
    if (isViewAttached()) {
        getView().showUserLoginOrRegisterError();
    }
 }

问题是,当我从移动和wifi连接断开设备时,onGetUserError()方法被正确调用,但无论如何都有一个未处理的异常导致我的应用程序崩溃。

这里是完整的堆栈跟踪:

https://gist.github.com/anonymous/859ab3811a3ca5c63998a40b877c41bb

我不知道如何摆脱这些崩溃!!

此致 马丁

---------- update 03.04.2017 --------- 还有另一个神秘...... 在三星Galaxy(S5)上,堆栈跟踪是相同的,但它是在我的错误处理程序方法中打印的!所以我能够正确捕获和处理异常。

 04-03 12:36:46.014 12078-12078/at.xxxx.yyyyapp 
 E/at.xxxx.yyyyapp.ui.startup.viewmodel.StartupViewModelImpl: 
 onGetUserError, getting user failed because of {}


 android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No 
 address associated with hostname)

 at libcore.io.Posix.android_getaddrinfo(Native Method)

 at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)

 at java.net.InetAddress.lookupHostByName(InetAddress.java:451)

 at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)

 at java.net.InetAddress.getAllByName(InetAddress.java:215)

 at okhttp3.Dns$1.lookup(Dns.java:39)

at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelec
tor.java:170)

 at 
 okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.java:136)

在我的其他测试设备(Nexus 5和6P)上调用了我的错误处理程序方法,但应用程序无论如何都会崩溃。

我不知道如何解决这个问题!

4 个答案:

答案 0 :(得分:1)

我遇到了完全相同的问题并且刚刚解决了。

当收到响应时,我没有实现onError处理,这是原因。

someObservable
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<Response>() {
      @Override public void onSubscribe(Disposable d) {
        disposables.add(d);
      }

      @Override public void onNext(Response response) {

      }

      @Override public void onError(Throwable e) {
        // implement this!!!
      }

      @Override public void onComplete() {

      }
    });
希望这会奏效。

答案 1 :(得分:0)

您可以在调用API方法之前检查网络连接。

slime-v2.19

将其用作

public static boolean isInternetAvailable(Context context) {
    ConnectivityManager mConMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    return mConMgr.getActiveNetworkInfo() != null
            && mConMgr.getActiveNetworkInfo().isAvailable()
            && mConMgr.getActiveNetworkInfo().isConnected();
}

这将是这个问题最简单的解决方案。 快乐的编码!

答案 2 :(得分:0)

嗯,首先,当您没有连接到互联网时,您不应该发送任何请求。

其次,你应该用.flatMap.

包裹你的api电话

你可以在这里找到一个例子,如果你从api调用中得到任何异常,这将抓住它。

示例:

 public Observable<User> getUser(@NonNull final UUID id) {
        return Observable.fromCallable(new Callable<User>() {
            @Override
            public User call() throws Exception {
                return api.getUser(id.toString());
            }
        }).map(user -> mapUser(user));
    } 

答案 3 :(得分:0)

我遇到了这样一个问题:如果服务器关闭或没有网络连接,改造会崩溃。 我不得不将 addCallAdapterFactory 添加到改造客户端。有很多关于如何添加自定义调用适配器工厂的教程。

Retrofit.Builder()
    .baseUrl(BuildConfig.API_URL)
    .addCallAdapterFactory(NetworkResponseAdapterFactory())
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create())
    .build()