【问题标题】:Why retrofit client crashes when there's no network connection?为什么在没有网络连接的情况下改造客户端会崩溃?
【发布时间】:2017-08-25 16:54:05
【问题描述】:

在我的 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

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

问候 马丁

---------更新 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)上,我的错误处理程序方法被调用,但应用程序仍然崩溃。

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

【问题讨论】:

标签: java android crash retrofit2 rx-java2


【解决方案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() {

      }
    });

希望这会奏效。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      其次,你应该用.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));
          } 
      

      【讨论】:

      • 嗨!我不能完全跟着你。您上面的代码无法编译。 lambda user->mapUser(user) 带有红色下划线“不存在类型变量 R 的实例,因此 Observable 符合 User”。注意,Api 定义中的 User 类和我的 UserService 中的 User 类是不一样的。它们通过 mapUser(..) 方法进行映射。
      • 好吧,删除这部分代码:.map(user -> mapUser(user)) 并将其添加到 .fromCallable. 之后,UI,编辑我的示例。
      • 我不明白 :) api.getUser(...) (这是改造接口的一个方法)返回一个 Observable 但返回类型Observable.fromCallable() 中重写的 call() 方法是 User。所以它不会再次编译。您的代码示例中方法的返回类型应该是 Observable
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多