2017-03-31 5 views
1

私のAndroidアプリケーションでは、ネットワークコールのためにRetrofit 2.2とRxJava 2を使用します。デバイスがネットワークに接続されている場合はすべて正常です。 モバイルとWi-Fiネットワークを無効にすると、アプリがクラッシュします。 奇妙なことに私はエラーを正しく処理できますが、アプリはとにかくクラッシュします。ネットワークに接続していないときにクライアントをクラッシュさせるのはなぜですか?

これは改修のためのAPIインタフェースは、次のとおりです。

public interface BackendApi { 

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

} 

次のメソッドは、私の見解モデルに加入される観測を返します。 Iが観測にサブスクライブビューモデルにおいて

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

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(); 
    } 
} 

エラー処理は問題が、であることを示しますと無線LAN接続、onGetUserError()メソッドは正しく呼び出されますが、とにかく私のアプリをクラッシュする未処理の例外があります。

はここで完全なスタックトレースです:私はどのようにこれらのクラッシュを取り除くためには考えている

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

!!

よろしく マーティン

----------更新2017年3月4日--------- 別のミステリ... はサムスンギャラクシー(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)では、エラーハンドラメソッドが呼び出されても、アプリがクラッシュします。

これを解決する方法はありません。

答えて

0

APIメソッドを呼び出す前に、ネットワーク接続を確認するだけで済みます。

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

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

これは、この質問に対して最も最も簡単な解決策になる

if (isInternetAvailable(context)) { 
     callAPIMethod(); 
    } else { 
     Toast.makeText(context, "No Internet Available", Toast.LENGTH_SHORT).show(); 
    } 

としてそれを使用してください。 ハッピーコーディング!

+0

あなたの答えをありがとう!私はこれが可能であることを知っていますが、私はこれが行く方法だとは想像できません。アプリには多くのネットワークコールがあります - 毎回インターネット接続をチェックすることはできません。私はRetrofi/RxJava/OkHttpで何か間違っていると思います... – maschin

+0

残念ながら、接続が常に存在するとは限りません。ネットワークにアクセスするたびに例外を処理するか、ネットワークが使用可能かどうかを確認する必要があります。アプリケーションがコード全体に散在するネットワークコールを持っていて、ネットワークがなくなる可能性がない場合は、アプリケーションを修正する必要があります。 –

0

ええと、インターネットに接続していないときは、まず何も要求しないでください。あなたはAPI呼び出しからの例外を取得する場合

第二に、あなたは、あなたがここでの例を見つけることができます.flatMap.

であなたの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)); 
    } 
+0

こんにちは! 私はあなたに正確に従うことができません。上記のコードはコンパイルされません。ラムダuser-> mapUser(user)には、オブザーバブルがUserに準拠するように、変数R(R)のインスタンスは存在しません。 Api定義のUserクラスは、UserServiceのUserクラスと同じではありません。それらはmapUser(..)メソッドを介してマップされます。 – maschin

+0

さて、コードのこの部分を削除してください.map(user - > mapUser(user))を.fromCallable。UIの後に追加して、私の例を編集しました。 –

+0

私はそれを得ることはありません:) api.getUser(Retrofit Interfaceのメソッド)はObservable を返します しかし、オーバーライドされた呼び出しの戻り値の型)メソッドは、Userです。だから、それは再びコンパイルされません。 コード例のメソッドの戻り値の型は、Observable maschin

0

私は正確に同じ問題を抱えていたし、ちょうど解決しました。

応答が受信され、その原因が原因で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() { 

     } 
    }); 

これがうまくいきます。

関連する問題