Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Android SDK

Gởi dữ liệu bằng Retrofit 2 HTTP Client cho Android

by
Difficulty:IntermediateLength:LongLanguages:

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)

Final product image
What You'll Be Creating

Retrofit là gì?

Retrofit là một type-safe HTTP client cho Android và Java. Retrofit giúp dễ dàng kết nối đến một dịch vụ REST ở trên web bằng cách dịch API thành các Interface của Java. Trong hướng dẫn này, tôi sẽ chỉ cho bạn cách sử dụng một trong các thư viện HTTP phổ biến nhất và thường được khuyến khích sử dụng cho Android.

Thư viện mạnh mẽ này giúp bạn dễ dàng lấy dữ liệu JSON hoặc XML, sau đó phân tích cú pháp thành Plain Old Java Objects (POJOs). Các yêu cầu GETPOSTPUTPATCH, và DELETE tất cả đều có thể được thực thi.

Giống như hầu hết các phần mềm nguồn mở khác, Retrofit được xây dựng trên nền của một số thư viện mạnh mẽ và công cụ khác. Đằng sau nó, Retrofit sử dụng OkHttp (từ cùng một nhà phát triển) để xử lý các yêu cầu mạng. Ngoài ra, Retrofit không tích hợp sẵn một bộ chuyển đổi JSON để phân tích từ JSON thành các đối tượng Java. Thay vào đó, nó hỗ trợ cho các thư viện chuyển đổi JSON sau đây để xử lý điều đó:

  • Gson: com.squareup.retrofit:converter-gson
  • Jackson: com.squareup.retrofit:converter-jackson
  • Moshi: com.squareup.retrofit:converter-moshi

Đối với Protocol buffers, Retrofit hỗ trợ:

  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire

Và đối với XML, Retrofit hỗ trợ:

  • Simple Framework: com.squareup.retrofit2:converter-simpleframework

Vậy tại sao lại sử dụng Retrofit?

Phát triển thư viện type-safe HTTP của riêng của bạn để giao tiếp với một REST API có thể thật sự rất khó: bạn phải xử lý nhiều khía cạnh, chẳng hạn như kết nối, bộ nhớ đệm, thử lại yêu cầu sai, luồng, phân tích phản hồi, xử lý lỗi và nhiều thứ khác. Mặt khác, Retrofit là một thư viện được tổ chức tốt, tài liệu hướng đầy đủ và đã thử nghiệm sẽ giúp bạn tiết kiệm rất nhiều thời gian quý báu và những đau đầu không cần thiết.

Trong hướng dẫn này, tôi sẽ giải thích cách làm thế nào để sử dụng Retrofit 2 để xử lý các yêu cầu mạng bằng cách xây dựng một ứng dụng đơn giản mà sẽ thực hiện các yêu cầu POST, PUT (để cập nhật các thực thể), và các yêu cầu DELETE. Tôi cũng sẽ chỉ cho bạn cách tích hợp với RxJava và cách hủy bỏ các yêu cầu. Chúng ta sẽ sử dụng API được cung cấp bởi JSONPlaceholder—đây là một REST API trực tuyến giả để thử nghiệm và tạo nguyên mẫu.

Hãy xem qua bài viết trước của tôi, Làm quen với Retrofit 2 HTTP Client, để tìm hiểu cách thực hiện các yêu cầu GET và cách tích hợp Retrofit với RxJava.

1. Tạo một dự án Android Studio

Mở Android Studio lên và tạo ra một dự án mới với một activity rỗng gọi là MainActivity.

create a new empty activity

2. Xác định các phụ thuộc

Sau khi tạo một dự án mới, định nghĩa các phụ thuộc sau đây trong build.gradle của bạn. Các phụ thuộc bao gồm thư viện Retrofit và Gson của Google để chuyển đổi JSON thành POJO (Plain Old Java Objects) cũng như Gson tích hợp của Retrofit.

Hãy chắc rằng bạn đã đồng bộ dự án của bạn sau khi thêm các phụ thuộc.

3. Thêm quyền truy cập Internet

Để thực hiện các hoạt động mạng, chúng ta cần phải bao thêm quyền INTERNET trong tập tin manifest: AndroidManifest.xml.

4. Tạo ra các Model một cách tự động

Chúng ta sẽ tạo ra các Model một cách tự động từ dữ liệu trả về JSON bằng cách tận dụng một công cụ rất hữu ích: jsonschema2pojo. Chúng ta muốn tạo một yêu cầu POST (tạo ra một nguồn tài nguyên mới) trên API. Nhưng trước khi chúng ta thực thi yêu cầu này, chúng ta cần phải biết các phản hồi JSON mà chúng ta mong muốn khi nó được thực thi thành công để cho Retrofit có thể phân tích phản hồi JSON và dịch nó thành các đối tượng Java. Theo API, nếu chúng ta gửi dữ liệu sau đây trong một yêu cầu POST:

Chúng ta sẽ nhận được các phản hồi sau:

Ánh xạ dữ liệu JSON sang Java

Sao chép mẫu dữ liệu trả về từ phần trước. Bây giờ hãy truy cập jsonschema2pojo và dán phản hồi JSON vào hộp nhập liệu. Chọn Source type là JSON, Annotation style là Gson, bỏ chọn Allow additional properties và đổi tên lớp từ Example thành Post.

jsonschema2pojo input

Sau đó nhấp vào nút Preview để tạo ra các đối tượng Java.

jsonschema2pojo output

Bạn có thể ngạc nhiên về các chú thích @SerializedName@Expose  làm gì trong code được tạo ra! Đừng lo, tôi sẽ giải thích tất cả!

Chú thích @SerializedName cần cho Gson ánh xạ các khoá JSON thành các trường đối tượng Java.

Trong trường hợp này, khoá JSON userId được ánh xạ tới trường userId của lớp. Nhưng lưu ý rằng vì chúng là như nhau, nên không cần phải bao gồm chú thích @SerializedName trên trường bởi vì Gson sẽ ánh xạ nó một cách tự động cho chúng ta.

Chú thích @Expose chỉ ra rằng thành viên lớp nên được trình bày cho JSON serialization hoặc deserialization.

Nhập các Data Model vào Android Studio

Bây giờ hãy quay trở lại Android Studio. Tạo một gói con mới bên trong gói main và đặt tên là data. Bên trong gói vừa mới được tạo ra, hãy tạo một gói và đặt tên là model. Bên trong gói này, tạo ra một lớp Java mới và đặt tên nó là Post. Bây giờ sao chép lớp Post được tạo ra bởi jsonschema2pojo và dán nó bên trong lớp Post mà bạn đã tạo.

Ngoài các hàm getter và setter, tôi cũng thêm phương thức toString(). (Trong Intellij, bạn có thể sử dụng lệnh Generate để thực hiện điều này dễ dàng: Alt-Insert trên Windows hoặc Command-N trên macOS.)

5. Tạo đối tượng Retrofit

Để phát đi các yêu cầu mạng đến một RESTful API bằng Retrofit, chúng ta cần tạo ra một đối tượng bằng cách sử dụng lớp Retrofit Builder và cấu hình nó với một URL cơ sở.

Tạo một gói mới bên trong gói data và đặt tên nó là remote. Bây giờ, bên trong gói này, tạo một lớp Java và đặt tên nó là RetrofitClient. Lớp này sẽ tạo ra một singleton của Retrofit trong phương thức getClient(String baseUrl) và trả nó về cho hàm gọi.

Như tôi đã đề cập trước đó, Retrofit cần một URL cơ sở để xây dựng nên đối tượng của nó, do đó, chúng ta sẽ truyền qua nó một URL khi gọi RetrofitClient.getClient(String baseUrl). URL này sau đó sẽ được sử dụng để xây dựng đối tượng ở dòng 13. Chúng ta cũng xác định bộ chuyển đổi JSON mà chúng ta cần (Gson) ở dòng 14.

6. Tạo API Interface

Bên trong các gói remote, tạo ra một Interface và gọi nó là APIService. Interface này có chứa các phương thức mà chúng ta sẽ sử dụng để chạy các yêu cầu HTTP chẳng hạn như POST, PUT, và DELETE. Hãy bắt đầu với yêu cầu POST.

Nhìn vào lớp APIService, chúng ta có một phương thức gọi là savePost(). Trên cùng của phương thức là chú thích @POST, nó chỉ ra rằng chúng ta muốn thực hiện một yêu cầu POST khi phương thức này được gọi. Giá trị tham số cho chú thích @POST là một endpoint—đó là /posts. Vì vậy, URL đầy đủ sẽ là http://jsonplaceholder.typicode.com/posts.

Được rồi, vậy còn @FormUrlEncoded thì sao? Điều này sẽ chỉ ra rằng các yêu cầu sẽ có kiểu MIME của nó (một tiêu đề trường xác định các định dạng của body của một yêu cầu hoặc phản hồi HTTP) được thiết lập thành application/x-www-form-urlencoded và đồng thời tên trường và giá trị của nó sẽ là UTF-8 encoded trước URI-encoded. Chú thích @Field("key") với tên tham số phải khớp với tên API mong muốn. Retrofit chuyển đổi toàn bộ các giá trị thành các chuỗi bằng cách sử dụng String.valueOf(Object), và các chuỗi sau đó ở trong hình thức mã hoá của URL. Các giá trị null được bỏ qua.

Ví dụ: gọi APIService.savePost("My Visit To Lagos", "I visited...", 2) in ra một body của yêu cầu là title=My+Visit+To+Lagos&body=I+Visit...&userId=2.

Sử dụng chú thích @Body

Chúng ta cũng có thể sử dụng chú thích @Body trên một số phương thức dịch vụ thay vì chỉ định một body của yêu cầu form-style với một số trường riêng. Đối tượng sẽ được serialize bằng cách sử dụng đối tượng Retrofit Converter được thiết lập suốt quá trình tạo. Điều này chỉ được sử dụng khi thực hiện một trong hai yêu cầu POST hoặc PUT.

7. Tạo các tiện ích API

Chúng ta sẽ tạo ra một lớp tiện ích. Vì vậy, hãy tạo một lớp trong data.remote và đặt tên nó là ApiUtils. Lớp này sẽ có URL cơ sở như là một biến tĩnh và cũng sẽ cung cấp interface APIService bằng một phương thức tĩnh getAPIService() cho phần còn lại của ứng dụng của chúng ta.

Đảm bảo rằng bạn kết thúc URL bằng một dấu /.

8. Tạo Layout

Tập tin activity_main.xml là layout cho MainActivity của chúng ta. Layout này sẽ có một trường Text Edit cho title và một cái khác cho phần body của bài post. Nó cũng bao gồm một nút để gửi bài post đến API.

9. Thực thi yêu cầu POST

Trong phương thức onCreate() của MainActivity, chúng ta khởi tạo một đối tượng của interface APIService (dòng thứ 14). Chúng ta cũng khởi tạo các trường EditText và một nút submit sẽ gọi phương thức sendPost() khi nhấn vào (dòng thứ 22).

Trong phương thức sendPost(String, String) ở trong lớp MainActivity, chúng ta truyền vào title và body của bìa post vào phương thức này. Những gì mà phương thức này làm là gọi phương thức savePost(String, String) của interface của dịch vụ API của chúng ta, công việc của nó là để thực một yêu cầu POST để gửi title và body cho API. Phương thức showResponse(String response) sẽ hiển thị phản hồi lên trên màn hình.

Phương thức savePost(String, String) trong đối tượng mAPIService của lớp APIService sẽ trả về một đối tượng Call có một phương thức được gọi là enqueue(Callback<T> callback).

Hiểu về enqueue()

enqueue() gửi yêu cầu và thông báo cho ứng dụng của bạn một cách không đồng bộ với một hàm callback khi có một phản hồi. Vì yêu cầu này là không đồng bộ, nên Retrofit xử lý việc thực thi trên một tác vụ chạy nền vì thế mà Giao diện Người dùng không bị ảnh hưởng.

Để sử dụng phương thức enqueue(), bạn phải cài đặt hai phương thức callback: onResponse()onFailure(). Chỉ có một trong hai phương thức này sẽ được gọi để đáp ứng một yêu cầu nhất định.

  • onResponse(): được gọi khi nhận được một phản hồi HTTP. Phương thức này được gọi khi có một phản hồi mà có thể được xử lý một cách chính xác ngay cả khi máy chủ trả về một thông báo lỗi. Vì vậy nếu bạn nhận được một code trạng thái là 404 hoặc 500, phương thức này sẽ vẫn được gọi. Để có được code trạng thái để bạn xử lý các tình huống dựa trên chúng, bạn có thể sử dụng phương thức response.code(). Bạn cũng có thể sử dụng phương thức isSuccessful() để tìm ra code trạng thái trong khoảng 200-300, xác định một yêu cầu thành công.
  • onFailure(): được gọi khi một ngoại lệ kết nối mạng xảy ra trong quá trình giao tiếp đến máy chủ, hoặc khi một ngoại lệ bất ngờ xảy ra trong quá trình xử lý yêu cầu hoặc xử lý phản hồi.

Các yêu cầu đồng bộ

Để thực hiện một yêu cầu đồng bộ, bạn có thể sử dụng phương thức execute() trong một đối tượng Call. Nhưng lưu ý rằng các phương thức đồng bộ trên tác vụ chính/UI sẽ chặn bất kỳ hành động nào của người dùng. Vì vậy, đừng thực hiện các phương thức đồng bộ trên tác vụ chính/UI của Android! Thay vào đó, hãy chạy chúng trên một tác vụ nền.

Sử dụng RxJava

RxJava mặc định được tích hợp vào Retrofit 1, nhưng trong Retrofit 2 bạn cần bao gồm một số phụ thuộc phụ. Retrofit đi kèm với một adapter mặc định để thực thi các đối tượng Call. Vì vậy, bạn có thể thay đổi cơ chế thực thi của Retrofit để bao gồm RxJava bằng cách bao gồm CallAdapter của RxJava. Đây là các bước:

Bước 1

Thêm các phụ thuộc.

Bước 2

Thêm CallAdapter RxJavaCallAdapterFactory.create() mới khi xây dựng một đối tượng Retrofit (dòng 5).

Bước 3

Cập nhật phương thức savePost(String title, String body, String userId) của APIService để trở thành một Observable.

Bước 4

Khi thực hiện các yêu cầu, người đăng ký vô danh của chúng ta phản hồi các dòng của người quan sát mà phát ra các sự kiện, trong trường hợp chúng ta là Post. Phương thức onNext sau đó được gọi khi người đăng ký của chúng ta nhận được bất kỳ sự kiện nào, sau đó được truyền cho phương thức showResponse(String response) của chúng ta.

Hãy đọc hướng dẫn Bắt đầu với ReactiveX trên Android bởi Ashraff Hathibelagal để tìm hiểu thêm về RxJava và RxAndroid.

10. Chạy thử ứng dụng

Đến thời điểm này, bạn có thể chạy ứng dụng và nhấn nút Submit khi bạn đã nhập vào một title và body. Phản hồi từ các API sẽ được hiển thị bên dưới nút submit.

final app screenshot

11. Thực thi một yêu cầu PUT

Bây giờ thì chúng ta đã biết cách làm thế nào để thực thi một yêu cầu POST, bây giờ chúng ta hãy xem cách thực thi một yêu cầu PUT để cập nhật các thực thể. Thêm phương thức mới sau đây vào lớp APIService.

Để cập nhật một bài Post từ API, chúng ta có endpoint /posts/ {id} với {id} là thay thế bởi id của bài Post mà chúng ta muốn cập nhật. Chú thích @Path là tên thay thế cho phân đoạn {id} của một URL. Lưu ý rằng các giá trị được chuyển đổi thành chuỗi bằng cách sử dụng String.valueOf(Object) và URL mã hóa. Nếu giá trị đã được mã hóa, bạn có thể vô hiệu hóa URL mã hóa như thế này: @Path(value="name", encode=true).

12. Thực thi một yêu cầu DELETE

Hãy cùng xem cách thực thi một yêu cầu DELETE. Sử dụng JSONPlaceholder API, để xóa một nguồn bài Post, endpoint cần thiết là /posts/{id} với phương thức DELETE của HTTP. Quay trở lại interface APIService, chúng ta chỉ cần bao gồm phương thức deletePost() sẽ thực thi nó. Chúng ta tryền id của bài post vào trong phương thức, và nó được thay thế trong phân đoạn {id} của URL.

13. Hủy một yêu cầu

Giả sử rằng bạn muốn cung cấp cho người dùng khả năng hủy bỏ hoặc ngắt một yêu cầu. Điều này rất dễ dàng để thực hiện trong Retrofit. Lớp Call của Retrofit có một phương thức gọi là cancel() mà sẽ thực hiện điều đó (ở dòng 30 bên dưới). Phương thức này sẽ kích hoạt phương thức onFailure() trong hàm callback.

Phương thức này có thể được gọi, ví dụ, nếu không có kết nối internet hoặc khi một ngoại lệ bất ngờ xảy ra trong quá trình tạo ra yêu cầu hoặc xử lý phản hồi. Vì vậy để biết yêu cầu đã được hủy bỏ hay chưa, sử dụng phương thức isCanceled() trong lớp Call (dòng 18).

Kết luận

Trong hướng dẫn này, bạn đã tìm hiểu về Retrofit: lý do tại sao bạn nên sử dụng nó và làm thế nào để tích hợp nó trong dự án của bạn để thực hiện các yêu cầu POST, PUT, DELETE và hủy bỏ các yêu cầu. Bạn cũng học được cách làm thế nào để tích hợp RxJava với nó. Trong bài tiếp theo của tôi về việc sử dụng Retrofit, tôi sẽ chỉ cho bạn cách làm thế nào để tải lên tập tin.

Để tìm hiểu thêm về Retrofit, hãy tham khảo tài liệu hướng dẫn chính thức. Và đọc một số bài hướng dẫn và các khóa học của chúng tôi về phát triển Android ở đây tại Envato Tuts+!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.