Pengenalan Retrofit

1. Gambaran keseluruhan

Retrofit adalah klien HTTP yang selamat digunakan untuk Android dan Java - dikembangkan oleh Square (Dagger, Okhttp).

Dalam artikel ini, kami akan menerangkan cara menggunakan Retrofit, dengan fokus pada ciri yang paling menarik. Lebih penting lagi kita akan membincangkan API segerak dan tidak segerak, cara menggunakannya dengan pengesahan, pembalakan, dan beberapa amalan pemodelan yang baik.

2. Menetapkan Contoh

Kita akan mulakan dengan menambahkan perpustakaan Retrofit dan penukar Gson:

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

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

3. Pemodelan API

Retrofit memodelkan titik akhir REST sebagai antara muka Java, menjadikannya sangat mudah difahami dan dimakan.

Kami akan memodelkan API pengguna dari GitHub; ini mempunyai titik akhir GET yang mengembalikannya dalam format JSON:

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

Retrofit berfungsi dengan memodelkan URL asas dan dengan membuat antara muka mengembalikan entiti dari titik akhir REST.

Untuk tujuan kesederhanaan kita akan mengambil sebahagian 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 }

Kami dapat melihat bahawa kami hanya mengambil subkumpulan sifat untuk contoh ini. Retrofit tidak akan mengeluh tentang kehilangan harta tanah - kerana ia hanya memetakan apa yang kita perlukan , bahkan tidak akan mengeluh jika kita menambahkan harta yang tidak ada di JSON.

Sekarang kita boleh beralih ke pemodelan antara muka, dan menjelaskan beberapa penjelasan 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 disertakan dengan anotasi cukup untuk alat menghasilkan pelaksanaan yang berfungsi.

The @GET anotasi memberitahu pelanggan yang HTTP kaedah untuk penggunaan dan di mana sumber, jadi sebagai contoh, dengan menyediakan URL pangkal "//api.github.com" ia akan menghantar permintaan untuk "//api.github.com / pengguna ”.

“/” Teratas pada URL relatif kami memberitahu Retrofit bahawa ia adalah jalan mutlak pada hos.

Perkara lain yang perlu diperhatikan adalah bahawa kita menggunakan parameter @Query sepenuhnya pilihan , yang dapat dinyatakan sebagai nol jika kita tidak memerlukannya, alat ini akan mengurus mengabaikan parameter ini jika tidak mempunyai nilai.

Dan yang terakhir, @Path membolehkan kami menentukan parameter jalan yang akan ditempatkan dan bukannya markup yang kami gunakan di jalan tersebut.

4. API segerak / tidak segerak

Untuk membuat panggilan permintaan HTTP, kita perlu membina 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 pembina yang sesuai untuk membina objek yang diperlukan. Ia memerlukan URL asas yang akan digunakan untuk setiap panggilan perkhidmatan dan kilang penukar - yang mengurus penguraian data yang kami kirimkan dan juga respons yang kami terima.

Dalam contoh ini, kita akan menggunakan GsonConverterFactory , yang akan memetakan data JSON kami ke kelas Pengguna yang kami tentukan sebelumnya.

Penting untuk diperhatikan bahawa kilang yang berbeza melayani tujuan yang berbeza, jadi ingatlah bahawa kami juga dapat menggunakan kilang untuk XML, proto-buffer atau bahkan membuatnya untuk protokol khusus. Untuk senarai kilang yang telah dilaksanakan, kita boleh lihat di sini.

Ketergantungan terakhir adalah OKHttpClient - yang merupakan klien HTTP & HTTP / 2 untuk aplikasi Android dan Java. Ini akan memastikan penyambungan ke pelayan dan penghantaran dan pengambilan maklumat. Kami juga dapat menambahkan tajuk dan pencegat untuk setiap panggilan, yang akan kami lihat di bahagian pengesahan kami.

Sekarang kita mempunyai objek Retrofit, kita dapat membuat panggilan perkhidmatan kita, mari kita lihat bagaimana melakukan ini dengan cara segerak:

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 mengurus pembinaan antara muka perkhidmatan kami dengan memasukkan kod yang diperlukan untuk membuat permintaan, berdasarkan penjelasan sebelumnya.

Setelah itu, kami mendapat objek Panggilan yang digunakan untuk melaksanakan permintaan ke GitHub API. Kaedah yang paling penting di sini adalah eksekusi , yang digunakan untuk melaksanakan panggilan secara serentak dan akan menyekat utas semasa semasa memindahkan data.

Setelah panggilan berjaya dilaksanakan, kita dapat mengambil bahagian respons - sudah ada pada objek pengguna - terima kasih kepada GsonConverterFactory kami .

Membuat panggilan segerak sangat mudah, tetapi biasanya, kami menggunakan permintaan tidak segerak yang menyekat:

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 bukannya kaedah eksekusi, kami menggunakan kaedah enqueue - yang mengambil antara muka Callback sebagai parameter untuk menangani kejayaan atau kegagalan permintaan. Perhatikan bahawa ini akan dilaksanakan dalam utas yang berasingan.

Setelah panggilan selesai dengan jayanya, kami dapat mengambil semula badan dengan cara yang sama seperti sebelumnya.

5. Membuat Kelas ServiceGenerator yang Boleh Digunakan Semula

Sekarang setelah kita melihat bagaimana membina objek Retrofit dan bagaimana menggunakan API, kita dapat melihat bahawa kita tidak mahu terus menulis pembangun berulang-ulang.

Apa yang kami mahukan adalah kelas yang boleh digunakan semula yang membolehkan kami membuat objek ini sekali dan menggunakannya semula sepanjang hayat aplikasi kami:

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 melanjutkan kelas GitHubServiceGenerator kami :

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 kelas kami, kami dapat melihat bagaimana kami menambahkan HttpLoggingInterceptor , dan kami menetapkannya untuk pembalakan asas, yang akan mencatat masa yang diperlukan untuk membuat permintaan, titik akhir, status untuk setiap permintaan, dll.

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

8. Kesimpulannya

Dalam panduan yang luas ini, kami melihat perpustakaan Retrofit yang sangat baik dengan memfokuskan pada Sync / Async APInya, beberapa amalan terbaik pemodelan, pengesahan, dan pembalakan.

Perpustakaan boleh digunakan dengan cara yang sangat kompleks dan berguna; untuk kes penggunaan lanjutan dengan RxJava, lihat tutorial ini.

Dan, seperti biasa, kod sumber boleh didapati di GitHub.