Pengantar Retrofit

1. Ikhtisar

Retrofit adalah klien HTTP tipe-aman untuk Android dan Java - dikembangkan oleh Square (Dagger, Okhttp).

Pada artikel ini, kami akan menjelaskan cara menggunakan Retrofit, dengan fokus pada fitur-fiturnya yang paling menarik. Lebih khusus lagi kita akan membahas API sinkron dan asinkron, cara menggunakannya dengan otentikasi, pencatatan, dan beberapa praktik pemodelan yang baik.

2. Menyiapkan Contoh

Kami akan mulai dengan menambahkan perpustakaan Retrofit dan konverter Gson:

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

Untuk versi terbaru, lihat Retrofit dan converter-gson di repositori Maven Central.

3. Pemodelan API

Retrofit memodelkan titik akhir REST sebagai antarmuka Java, membuatnya sangat mudah dipahami dan dikonsumsi.

Kami akan membuat model API pengguna dari GitHub; ini memiliki titik akhir GET yang mengembalikan ini dalam format JSON:

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

Retrofit bekerja dengan memodelkan melalui URL dasar dan dengan membuat antarmuka mengembalikan entitas dari titik akhir REST.

Untuk tujuan kesederhanaan, kami akan mengambil sebagian kecil dari JSON dengan memodelkan kelas Pengguna kami yang akan mengambil nilai ketika kami menerimanya:

public class User { private String login; private long id; private String url; // ... // standard getters an setters }

Kita dapat melihat bahwa kita hanya mengambil subset properti untuk contoh ini. Retrofit tidak akan mengeluh tentang properti yang hilang - karena hanya memetakan apa yang kita butuhkan , bahkan tidak akan mengeluh jika kita menambahkan properti yang tidak ada di JSON.

Sekarang kita dapat beralih ke pemodelan antarmuka, dan menjelaskan beberapa anotasi 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); }
    

Metadata yang diberikan dengan anotasi sudah cukup bagi alat untuk menghasilkan implementasi yang berfungsi.

The @GET penjelasan memberitahu klien yang HTTP metode untuk digunakan dan di mana sumber daya, jadi misalnya, dengan menyediakan URL dasar “//api.github.com” itu akan mengirimkan permintaan ke “//api.github.com / pengguna ”.

Awalan "/" di URL relatif kita memberi tahu Retrofit bahwa ini adalah jalur absolut pada host.

Hal lain yang perlu diperhatikan adalah kita menggunakan parameter @Query yang sepenuhnya opsional , yang dapat diteruskan sebagai null jika kita tidak membutuhkannya, alat akan menangani pengabaian parameter ini jika tidak memiliki nilai.

Dan yang tak kalah pentingnya, @Path memungkinkan kami menentukan parameter jalur yang akan ditempatkan sebagai ganti markup yang kami gunakan di jalur.

4. API Sinkron / Asinkron

Untuk membuat panggilan permintaan HTTP, kita perlu membuat objek Retrofit terlebih dahulu:

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

Retrofit menyediakan pembangun yang nyaman untuk membangun objek yang kami butuhkan. Ini membutuhkan URL dasar yang akan digunakan untuk setiap panggilan layanan dan pabrik konverter - yang menangani penguraian data yang kami kirim dan juga tanggapan yang kami dapatkan.

Dalam contoh ini, kita akan menggunakan GsonConverterFactory , yang akan memetakan data JSON kita ke kelas User yang kita definisikan sebelumnya.

Penting untuk diperhatikan bahwa pabrik yang berbeda melayani tujuan yang berbeda, jadi perlu diingat bahwa kami juga dapat menggunakan pabrik untuk XML, proto-buffer atau bahkan membuatnya untuk protokol khusus. Untuk daftar pabrik yang sudah diimplementasikan, kita bisa melihat di sini.

Ketergantungan terakhir adalah OKHttpClient - yang merupakan klien HTTP & HTTP / 2 untuk aplikasi Android dan Java. Ini akan menangani koneksi ke server dan pengiriman serta pengambilan informasi. Kita juga bisa menambahkan header dan interseptor untuk setiap panggilan, yang akan kita lihat di bagian otentikasi.

Sekarang setelah kita memiliki objek Retrofit, kita dapat membuat panggilan layanan kita, mari kita lihat bagaimana melakukan ini dengan cara sinkron:

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

Di sini, kita dapat melihat bagaimana Retrofit menangani konstruksi antarmuka layanan kita dengan memasukkan kode yang diperlukan untuk membuat permintaan, berdasarkan anotasi kita sebelumnya.

Setelah itu, kita mendapatkan objek Call yang digunakan untuk menjalankan permintaan ke GitHub API. Metode terpenting di sini adalah mengeksekusi , yang digunakan untuk mengeksekusi panggilan secara sinkron dan akan memblokir utas saat ini saat mentransfer data.

Setelah panggilan berhasil dijalankan, kita dapat mengambil isi respons - yang sudah ada di objek pengguna - berkat GsonConverterFactory .

Membuat panggilan sinkron sangat mudah, tetapi biasanya, kami menggunakan permintaan asinkron non-pemblokiran:

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

Sekarang alih-alih metode eksekusi, kami menggunakan metode enqueue - yang menggunakan antarmuka Callback sebagai parameter untuk menangani berhasil atau tidaknya permintaan. Perhatikan bahwa ini akan dijalankan di utas terpisah.

Setelah panggilan berhasil diselesaikan, kita dapat mengambil tubuh dengan cara yang sama seperti yang kita lakukan sebelumnya.

5. Membuat Kelas ServiceGenerator yang Dapat Digunakan Kembali

Sekarang setelah kita melihat bagaimana membangun objek Retrofit kita dan bagaimana menggunakan API, kita dapat melihat bahwa kita tidak ingin terus-menerus menulis buildernya berulang kali.

Yang kita inginkan adalah kelas yang dapat digunakan kembali yang memungkinkan kita membuat objek ini sekali dan menggunakannya kembali selama masa pakai aplikasi kita:

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 

Sekarang mari kita memperluas kelas GitHubServiceGenerator kita :

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

Ini adalah bentuk terakhir dari kelas kita, kita dapat melihat bagaimana kita menambahkan HttpLoggingInterceptor , dan kita mengaturnya untuk pencatatan dasar, yang akan mencatat waktu yang dibutuhkan untuk membuat permintaan, titik akhir, status untuk setiap permintaan, dll.

Penting untuk melihat bagaimana kami memeriksa apakah pencegat itu ada, jadi kami tidak menambahkannya dua kali secara tidak sengaja.

8. Kesimpulan

Dalam panduan ekstensif ini, kami melihat perpustakaan Retrofit yang sangat baik dengan berfokus pada API Sinkronisasi / Asinkron, beberapa praktik terbaik pemodelan, autentikasi, dan pencatatan.

Perpustakaan dapat digunakan dengan cara yang sangat kompleks dan berguna; untuk kasus penggunaan lanjutan dengan RxJava, silakan lihat tutorial ini.

Dan, seperti biasa, kode sumber dapat ditemukan di GitHub.