web-dev-qa-db-ja.com

メインスレッドのRetrofitコールバック

次のような呼び出しで:

@GET("/user/{id}/data")
void getUserData(@Path("id") int id, Callback<Data> cb);

コールバックはメインスレッドで実行されることになっています(RxJavaを使用していない場合)。私の質問は:

  1. 解析はどこで行われますか(プロセス応答にXMLコンバーターを使用していると仮定します)。これはメインスレッドですか、それとも別のスレッドですか?コンバーターの実装に依存しますか?
  2. いくつかの(重い)検証ルール/ビジネスルールを含める必要がある場合、callable内に新しいスレッドを生成する必要がありますか?それとも、コールバックメソッドでそれを実行しても問題ありませんか?

自分でスレッド管理を回避して(またはIntentServiceなどの他のアプローチを使用して)Webサービスからアクティビティのデータを取得する方法を探していますが、RxJavaを使用することも恐れています(実験的なサポートのため)。この問題に対処するための別の提案されたアプローチはありますか?

15
Jaguar

解析はどこで行われますか(プロセス応答にXMLコンバーターを使用していると仮定します)。これはメインスレッドですか、それとも別のスレッドですか?コンバーターの実装に依存しますか?

使用するコンバーターに関係なく、常にバックグラウンドスレッド。

いくつかの(重い)検証ルール/ビジネスルールを含める必要がある場合、callable内に新しいスレッドを生成する必要がありますか?それとも、コールバックメソッドでそれを実行しても問題ありませんか?

これはかなり主観的なものであり、それに取り組む方法はたくさんあります。 Callbackは、デフォルトでメインスレッドで実行されます。

カスタムExecutorRestAdapter.Builderに指定することにより、コールバックが呼び出されるスレッドを変更できます。これは、そのRestAdapterによって構築されたすべてのサービスに影響しますが、それはあなたが望むものではないかもしれません。

実行したい作業をUIの更新と並行して実行できる場合(たとえば、軽量キャッシュ)、Callbackから別のスレッドを生成(またはエグゼキューターにエンキュー)しても問題はありません。

UIに通知する前にコストのかかる作業を行う必要がある場合は、メソッドを同期(コールバックなし)に切り替えて、自分でスレッド化することをお勧めします。このようにして、HTTP呼び出しの前後にコストのかかる操作(ファイルI/O、キャッシュ、変換、検証など)を実行できます。

私たちは現在、あなたが求めているものにRxJava(Retrofitは実験的にサポートしています)を使用しています:

interface Foo {
  @GET("/")
  Observable<Foo> getFoo(String bar);
}

foo.getFoo()
  .mapMany(new ExpensiveOperationFunction())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Observer<TransformedFoo>() { .. });
20
Jake Wharton