1概要


Retrofit

は、AndroidとJava用のタイプセーフなHTTPクライアントです。Square(http://square.github.io/dagger/[Dagger]、http:/によって開発されました。/square.github.io/okhttp/[Okhttp])。

この記事では、Retrofitの使い方について、その最も興味深い機能を中心に説明します。特に注目すべきは、同期および非同期API、それを認証、ログ記録、およびいくつかの優れたモデリング手法と共に使用する方法です。


2例の設定

まず、RetrofitライブラリとGsonコンバーターを追加します。

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>converter-gson</artifactId>
    <version>2.3.0</version>
</dependency>

最新版については、https://search.maven.org/classic/#search%7C1%7Cg%3A%22com.squareup.retrofit2%22%20AND%20a%3A%22retrofit%22[をご覧ください。]およびhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.squareup.retrofit2%22%20AND%20a%3A%22converter-gson%22[converter-gson]Maven Centralリポジトリで。


3 APIモデリング

RetrofitはRESTエンドポイントをJavaインターフェースとしてモデル化しているため、理解しやすく消費しやすくなっています。

GitHubのhttps://api.github.com/users[user API]をモデル化します。これはJSON形式でこれを返す

GET

エンドポイントを持ちます。

{
  login: "mojombo",
  id: 1,
  url: "https://api.github.com/users/mojombo",
  ...
}

Retrofitは、ベースURLをモデル化し、インターフェースがRESTエンドポイントからエンティティを返すようにすることで機能します。

わかりやすくするために、JSONのごく一部を取り上げて、

User

クラスをモデル化します。このクラスは、受け取ったときに値を取ります。

public class User {
    private String login;
    private long id;
    private String url;
   //...

   //standard getters an setters

}

この例では、プロパティのサブセットしか使用していないことがわかります。

Retrofitは欠けているプロパティについて不満を言うことはありません – それは私たちが必要とするものをマッピングするだけなので

、JSONにないプロパティを追加しようとしても不平を言うことはありません。

それでは、インターフェースのモデリングに移り、いくつかのRetrofitアノテーションについて説明しましょう。

public interface UserService {

    @GET("/users")
    public Call<List<User>> getUsers(
      @Query("per__page") int per__page,
      @Query("page") int page);

    @GET("/users/{username}")
    public Call<User> getUser(@Path("username") String username);
}

アノテーション付きで提供されるメタデータは、ツールが実用的な実装を生成するのに十分です。


@ GET

アノテーションは、どのHTTPメソッドをどのリソースで使用するかをクライアントに指示します。たとえば、「https://api.github.com」のベースURLを提供することで、「https://」にリクエストを送信します。 api.github.com/users」を参照してください。

<a href=””> ____と同じ規則が適用されることに注意してください – 相対URLの先頭の「/」は、それがホスト上の絶対パスであることをRetrofitに伝えます。

もう1つ注意が必要なのは、完全にオプションの

@ Query

パラメータを使用することです。これは、必要ない場合はnullとして渡すことができます。値がない場合、ツールはこれらのパラメータを無視します。

そして最後に大事なことを言い忘れましたが、

@ Path

では、パスで使用したマークアップの代わりに配置されるパスパラメータを指定できます。


4同期/非同期API

HTTPリクエスト呼び出しを構築するには、最初にRetrofitオブジェクトを構築する必要があります。

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit retrofit = new Retrofit.Builder()
  .baseUrl("https://api.github.com/")
  .addConverterFactory(GsonConverterFactory.create())
  .client(httpClient.build())
  .build();

Retrofitは、必要なオブジェクトを構築するための便利なビルダーを提供します。

すべてのサービスコールに使用されるベースURLとコンバーターファクトリー

が必要です。これは、送信しているデータの解析と応答を処理します。

この例では、

GsonConverterFactory

を使用します。これは、前に定義した

User

クラスにJSONデータをマッピングすることになります。

ファクトリが異なると目的が異なるので、XML、プロトバッファ、またはカスタムプロトコル用にファクトリを作成することもできます。すでに実装されている工場の一覧については、https://github.com/square/retrofit/tree/master/retrofit-convertersを参照してください。

最後の依存関係は

OKHttpClient

です。これはHTTPです。

すべての通話にヘッダーとインターセプターを追加することもできます。これについては、認証のセクションで説明します。

これでRetrofitオブジェクトができたので、サービスコールを作成しましょう。これを同期的に行う方法を見てみましょう。

UserService service = retrofit.create(UserService.class);
Call<User> callSync = service.getUser("eugenp");

try {
    Response<User> response = callSync.execute();
    User user = response.body();
} catch (Exception ex) { ... }

ここでは、以前のアノテーションに基づいて、リクエストを行うために必要なコードをインジェクトすることによって、Retrofitがサービスインターフェイスの構築をどのように処理するかを確認できます。

その後、GitHub APIへのリクエストを実行するために使用されるものである

Call <User>

オブジェクトを取得します。


ここで最も重要な方法は

execute




__、

__です。これは呼び出しを同期的に実行するために使用され、データの転送中に現在のスレッドをブロックします。

呼び出しが正常に実行された後、

GsonConverterFactory

のおかげで、すでにユーザーオブジェクト上にある応答の本文を取得できます。

同期呼び出しを行うことは非常に簡単ですが、通常、非ブロッキング非同期要求を使用します。

UserService service = retrofit.create(UserService.class);
Call<User> callAsync = service.getUser("eugenp");

callAsync.enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        User user = response.body();
    }

    @Override
    public void onFailure(Call<User> call, Throwable throwable) {
        System.out.println(throwable);
    }
});

executeメソッドの代わりに、

enqueue

メソッドを使用します。これは、リクエストの成功または失敗を処理するためのパラメータとして

__Callback <User>

__interfaceを受け取ります。これは別のスレッドで実行されることに注意してください。

呼び出しが正常に終了したら、以前と同じ方法で本文を取得できます。


5再利用可能な

ServiceGenerator

クラスを作成する

Retrofitオブジェクトを作成する方法とAPIを消費する方法を見たので、ビルダーを何度も書き続けたくないことがわかります。

欲しいのは、このオブジェクトを一度作成してアプリケーションの存続期間中に再利用できるようにする再利用可能なクラスです。

public class GitHubServiceGenerator {

    private static final String BASE__URL = "https://api.github.com/";

    private static Retrofit.Builder builder
      = new Retrofit.Builder()
        .baseUrl(BASE__URL)
        .addConverterFactory(GsonConverterFactory.create());

    private static Retrofit retrofit = builder.build();

    private static OkHttpClient.Builder httpClient
      = new OkHttpClient.Builder();

    public static <S> S createService(Class<S> serviceClass) {
        return retrofit.create(serviceClass);
    }
}

Retrofitオブジェクトを作成するすべてのロジックは、この

GitHubServiceGenerator

クラスに移動しました。これにより、コードの繰り返しを防ぐ持続可能なクライアントクラスになります。

使い方の簡単な例を示します。

UserService service
  = GitHubServiceGenerator.createService(UserService.class);

たとえば、

RepositoryServiceを作成する場合、

このクラスを再利用して作成を単純化できます。

  • 次のセクション** では、これを拡張して認証機能を追加します。


6. 認証

ほとんどのAPIには、アクセスを保護するための認証があります。

前のジェネレータクラスを考慮して、

Authorization

ヘッダを持つJWTトークンを受け取るcreate serviceメソッドを追加します。

public static <S> S createService(Class<S> serviceClass, final String token ) {
   if ( token != null ) {
       httpClient.interceptors().clear();
       httpClient.addInterceptor( chain -> {
           Request original = chain.request();
           Request request = original.newBuilder()
             .header("Authorization", token)
             .build();
           return chain.proceed(request);
       });
       builder.client(httpClient.build());
       retrofit = builder.build();
   }
   return retrofit.create(serviceClass);
}

リクエストにヘッダを追加するには、

OkHttp

のインターセプタ機能を使う必要があります。これを行うには、以前に定義したビルダーを使用し、Retrofitオブジェクトを再構築します。

これは単純な認証の例ですが、インターセプターを使用すると、OAuth、ユーザー/パスワードなどの認証を使用できます。


7. ロギング

このセクションでは、ログ機能のために

GitHubServiceGenerator

をさらに拡張します。これは、すべてのプロジェクトでデバッグ目的に非常に重要です。

以前のインターセプターの知識を使用しますが、追加の依存関係が必要です。これはOkHttpの

HttpLoggingInterceptor

です。これを

pom.xml

に追加します。

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>logging-interceptor</artifactId>
    <version>3.9.0</version>
</dependency>

それでは、

GitHubServiceGenerator

クラスを拡張しましょう。

public class GitHubServiceGenerator {

    private static final String BASE__URL = "https://api.github.com/";

    private static Retrofit.Builder builder
      = new Retrofit.Builder()
        .baseUrl(BASE__URL)
        .addConverterFactory(GsonConverterFactory.create());

    private static Retrofit retrofit = builder.build();

    private static OkHttpClient.Builder httpClient
      = new OkHttpClient.Builder();

    private static HttpLoggingInterceptor logging
      = new HttpLoggingInterceptor()
        .setLevel(HttpLoggingInterceptor.Level.BASIC);

    public static <S> S createService(Class<S> serviceClass) {
        if (!httpClient.interceptors().contains(logging)) {
            httpClient.addInterceptor(logging);
            builder.client(httpClient.build());
            retrofit = builder.build();
        }
        return retrofit.create(serviceClass);
    }

    public static <S> S createService(Class<S> serviceClass, final String token) {
        if (token != null) {
            httpClient.interceptors().clear();
            httpClient.addInterceptor( chain -> {
                Request original = chain.request();
                Request.Builder builder1 = original.newBuilder()
                  .header("Authorization", token);
                Request request = builder1.build();
                return chain.proceed(request);
            });
            builder.client(httpClient.build());
            retrofit = builder.build();
        }
        return retrofit.create(serviceClass);
    }
}

これが私たちのクラスの最終的な形で、

HttpLoggingInterceptor

をどのように追加したかを見ることができます。そしてそれを基本ロギングのために設定しました。

インターセプターが存在するかどうかを確認する方法を確認することは重要です。誤って2回追加することはありません。


8結論

この広範なガイドでは、Sync/Async API、モデリング、認証、およびロギングのベストプラクティスに焦点を当てて、優れたRetrofitライブラリを調べました。

ライブラリは非常に複雑で便利な方法で使うことができます。 RxJavaの高度な使用例については、

このチュートリアル

を参照してください。

そして、いつものように、ソースコードはhttps://github.com/eugenp/tutorials/tree/master/libraries[over on GitHub]にあります。