개조 소개

1. 개요

Retrofit은 Square (Dagger, Okhttp)에서 개발 한 Android 및 Java 용 형식이 안전한 HTTP 클라이언트입니다.

이 기사에서는 가장 흥미로운 기능에 중점을두고 Retrofit을 사용하는 방법을 설명합니다. 특히 동기 및 비동기 API, 인증, 로깅 및 몇 가지 좋은 모델링 사례와 함께 사용하는 방법에 대해 설명합니다.

2. 예제 설정

Retrofit 라이브러리와 Gson 변환기를 추가하여 시작합니다.

 com.squareup.retrofit2 retrofit 2.3.0   com.squareup.retrofit2 converter-gson 2.3.0 

최신 버전의 경우 Maven Central 저장소에서 Retrofit 및 converter-gson을 살펴보세요.

3. API 모델링

Retrofit은 REST 엔드 포인트를 Java 인터페이스로 모델링하므로 이해하고 사용하기가 매우 간단합니다.

GitHub에서 사용자 API를 모델링합니다. 여기에는 JSON 형식으로 반환 하는 GET 엔드 포인트가 있습니다.

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

Retrofit은 기본 URL을 통해 모델링하고 인터페이스가 REST 끝점에서 엔터티를 반환하도록하는 방식으로 작동합니다.

간단하게하기 위해 값을 받았을 때 값을받을 User 클래스를 모델링하여 JSON의 작은 부분 을 취할 것입니다.

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
    
      getUsers( @Query("per_page") int per_page, @Query("page") int page); @GET("/users/{username}") public Call getUser(@Path("username") String username); }
    

주석과 함께 제공되는 메타 데이터는 도구가 작동하는 구현을 생성하기에 충분합니다.

@GET의 주석은 HTTP 그래서 예를 들어, "//api.github.com"의 기본 URL을 제공하여 사용하고있는 자원에 대한 방법, 그것은 //api.github.com "에 요청을 보내드립니다 클라이언트를 알려줍니다 / users”.

상대 URL의 선행 "/" 는 Retrofit에 호스트의 절대 경로임을 알려줍니다.

주목해야 할 또 다른 점은 완전히 선택적인 @Query 매개 변수를 사용한다는 것입니다.이 매개 변수는 필요하지 않은 경우 null로 전달할 수 있으며, 도구는 값이없는 경우 이러한 매개 변수를 무시합니다.

마지막으로 @Path를 사용하면 경로에서 사용한 마크 업 대신 배치 할 경로 매개 변수를 지정할 수 있습니다.

4. 동기 / 비동기 API

HTTP 요청 호출을 생성하려면 먼저 Retrofit 객체를 빌드해야합니다.

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

Retrofit은 필요한 개체를 구성하는 데 편리한 빌더를 제공합니다. 모든 서비스 호출에 사용될 기본 URL과 우리가 보내는 데이터의 구문 분석과 우리가받는 응답을 처리 하는 변환기 팩토리 가 필요합니다.

이 예제에서는 JSON 데이터를 앞서 정의한 User 클래스 에 매핑 할 GsonConverterFactory 를 사용할 것 입니다.

팩토리마다 다른 용도로 사용된다는 점에 유의하는 것이 중요하므로 XML, 프로토 버퍼를위한 팩토리를 사용하거나 사용자 지정 프로토콜을위한 팩토리를 만들 수도 있습니다. 이미 구현 된 공장 목록은 여기에서 확인할 수 있습니다.

마지막 종속성은 Android 및 Java 애플리케이션을위한 HTTP 및 HTTP / 2 클라이언트 인 OKHttpClient 입니다. 이것은 서버에 연결하고 정보의 전송 및 검색을 처리합니다. 또한 모든 호출에 대해 헤더와 인터셉터를 추가 할 수 있으며, 이는 인증 섹션에서 볼 것입니다.

이제 Retrofit 개체가 있으므로 서비스 호출을 구성 할 수 있습니다. 동기 방식으로이 작업을 수행하는 방법을 살펴 보겠습니다.

UserService service = retrofit.create(UserService.class); Call callSync = service.getUser("eugenp"); try { Response response = callSync.execute(); User user = response.body(); } catch (Exception ex) { ... }

여기에서 이전 주석을 기반으로 요청을 만드는 데 필요한 코드를 삽입하여 Retrofit이 서비스 인터페이스의 구성을 처리하는 방법을 볼 수 있습니다.

그 후 GitHub API에 대한 요청을 실행하는 데 사용되는 Call 객체를 얻습니다 . 여기서 가장 중요한 메서드는 execute입니다 . 이것은 호출을 동 기적으로 실행하는 데 사용되며 데이터를 전송하는 동안 현재 스레드를 차단합니다.

호출이 성공적으로 실행 된 후 GsonConverterFactory 덕분에 이미 사용자 객체에있는 응답 본문을 검색 할 수 있습니다 .

동기 호출을 만드는 것은 매우 쉽지만 일반적으로 비 차단 비동기 요청을 사용합니다.

UserService service = retrofit.create(UserService.class); Call callAsync = service.getUser("eugenp"); callAsync.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { User user = response.body(); } @Override public void onFailure(Call call, Throwable throwable) { System.out.println(throwable); } });

이제 execute 메소드 대신 요청의 성공 또는 실패를 처리하기 위해 Callback 인터페이스를 매개 변수로 사용하는 enqueue 메소드를 사용합니다 . 이것은 별도의 스레드에서 실행됩니다.

호출이 성공적으로 완료되면 이전과 동일한 방식으로 본문을 검색 할 수 있습니다.

5. 재사용 가능한 ServiceGenerator 클래스 만들기

이제 Retrofit 객체를 구성하는 방법과 API를 사용하는 방법을 보았으므로 빌더를 계속해서 작성하고 싶지 않다는 것을 알 수 있습니다.

우리가 원하는 것은이 객체를 한 번 만들고 응용 프로그램의 수명 동안 재사용 할 수있는 재사용 가능한 클래스입니다.

public class GitHubServiceGenerator { private static final String BASE_URL = "//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 createService(Class serviceClass) { return retrofit.create(serviceClass); } }

All the logic of creating the Retrofit object is now moved to this GitHubServiceGenerator class, this makes it a sustainable client class which stops the code from repeating.

Here's a simple example of how to use it :

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

Now if we, for example, were to create a RepositoryService, we could reuse this class and simplify the creation.

In the next section, we're going to extend it and add authentication capabilities.

6. Authentication

Most APIs have some authentication to secure access to it.

Taking into account our previous generator class, we're going to add a create service method, that takes a JWT token with the Authorization header :

public static  S createService(Class 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); }

To add a header to our request, we need to use the interceptor capabilities of OkHttp; we do this by using our previously define builder and by reconstructing the Retrofit object.

Note that this a simple auth example, but with the use of interceptors we can use any authentication such as OAuth, user/password, etc.

7. Logging

In this section, we're going to further extend our GitHubServiceGenerator for logging capabilities, which are very important for debugging purposes in every project.

We're going to use our previous knowledge of interceptors, but we need an additional dependency, which is the HttpLoggingInterceptor from OkHttp, let us add it to our pom.xml:

 com.squareup.okhttp3 logging-interceptor 3.9.0 

이제 GitHubServiceGenerator 클래스를 확장 해 보겠습니다 .

public class GitHubServiceGenerator { private static final String BASE_URL = "//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 createService(Class serviceClass) { if (!httpClient.interceptors().contains(logging)) { httpClient.addInterceptor(logging); builder.client(httpClient.build()); retrofit = builder.build(); } return retrofit.create(serviceClass); } public static  S createService(Class 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를 추가 한 방법을 볼 수 있으며, 요청을 만드는 데 걸린 시간, 끝점, 모든 요청에 ​​대한 상태 등을 기록하는 기본 로깅에 대해 설정할 수 있습니다.

인터셉터가 존재하는지 확인하는 방법을 살펴 보는 것이 중요하므로 실수로 두 번 추가하지 않습니다.

8. 결론

이 광범위한 가이드에서 우리는 Sync / Async API, 모델링, 인증 및 로깅의 몇 가지 모범 사례에 중점을 두어 우수한 Retrofit 라이브러리를 살펴 보았습니다.

라이브러리는 매우 복잡하고 유용한 방법으로 사용할 수 있습니다. RxJava의 고급 사용 사례에 대해서는이 자습서를 참조하십시오.

그리고 언제나처럼 소스 코드는 GitHub에서 찾을 수 있습니다.