Retrofit是Square公司開發的一個類型安全的HTTP客戶端庫,專為Android和Java設計。它基于OkHttp,提供了簡潔的API來處理網絡請求。Retrofit通過注解的方式將HTTP API轉換為Java接口,使得網絡請求的代碼更加簡潔和易于維護。
Retrofit的主要特點包括:
首先,在項目的build.gradle
文件中添加Retrofit和OkHttp的依賴:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
}
假設我們要請求一個返回JSON數據的API,首先需要定義一個數據模型類。例如,假設API返回的用戶信息如下:
{
"id": 1,
"name": "John Doe",
"email": "john.doe@example.com"
}
我們可以定義一個對應的Java類:
public class User {
private int id;
private String name;
private String email;
// Getters and setters
}
接下來,我們需要定義一個接口來描述API的請求。Retrofit通過注解來定義HTTP請求的類型、路徑、參數等。例如,定義一個獲取用戶信息的接口:
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface ApiService {
@GET("users/{id}")
Call<User> getUser(@Path("id") int userId);
}
在發起網絡請求之前,我們需要創建一個Retrofit實例。Retrofit提供了Retrofit.Builder
來配置和創建實例:
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static final String BASE_URL = "https://jsonplaceholder.typicode.com/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
最后,我們可以通過Retrofit實例發起網絡請求:
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ApiService apiService = RetrofitClient.getClient().create(ApiService.class);
Call<User> call = apiService.getUser(1);
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
User user = response.body();
// 處理用戶信息
} else {
// 處理錯誤
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
// 處理網絡錯誤
}
});
}
}
在某些情況下,我們可能需要動態地指定請求的URL。Retrofit允許我們在接口方法中使用@Url
注解來指定動態URL:
@GET
Call<User> getUser(@Url String url);
我們可以使用@Header
注解來添加請求頭:
@GET("users/{id}")
Call<User> getUser(@Path("id") int userId, @Header("Authorization") String authToken);
如果需要添加多個請求頭,可以使用@Headers
注解:
@Headers({
"Authorization: Bearer {token}",
"Accept: application/json"
})
@GET("users/{id}")
Call<User> getUser(@Path("id") int userId, @Path("token") String token);
Retrofit支持多種類型的請求參數,包括查詢參數、表單參數、路徑參數等。
@Query
注解: @GET("users")
Call<List<User>> getUsers(@Query("page") int page, @Query("limit") int limit);
@Field
注解: @FormUrlEncoded
@POST("users")
Call<User> createUser(@Field("name") String name, @Field("email") String email);
@Path
注解: @GET("users/{id}")
Call<User> getUser(@Path("id") int userId);
Retrofit支持文件上傳,可以使用@Multipart
和@Part
注解:
@Multipart
@POST("upload")
Call<ResponseBody> uploadFile(@Part MultipartBody.Part file);
在發起請求時,可以將文件轉換為MultipartBody.Part
:
File file = new File(filePath);
RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpeg"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
Call<ResponseBody> call = apiService.uploadFile(body);
call.enqueue(...);
Retrofit也支持文件下載,可以直接返回ResponseBody
:
@GET("download")
Call<ResponseBody> downloadFile();
在回調中,可以將ResponseBody
寫入文件:
Call<ResponseBody> call = apiService.downloadFile();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try (InputStream inputStream = response.body().byteStream();
FileOutputStream outputStream = new FileOutputStream(new File("downloaded_file.jpg"))) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
// 處理錯誤
}
});
在某些情況下,API返回的JSON數據可能不符合我們的數據模型。我們可以通過自定義Gson解析器來處理這種情況。
首先,創建一個自定義的TypeAdapter
:
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
public class UserTypeAdapter extends TypeAdapter<User> {
@Override
public void write(JsonWriter out, User user) throws IOException {
out.beginObject();
out.name("id").value(user.getId());
out.name("full_name").value(user.getName());
out.name("email_address").value(user.getEmail());
out.endObject();
}
@Override
public User read(JsonReader in) throws IOException {
User user = new User();
in.beginObject();
while (in.hasNext()) {
switch (in.nextName()) {
case "id":
user.setId(in.nextInt());
break;
case "full_name":
user.setName(in.nextString());
break;
case "email_address":
user.setEmail(in.nextString());
break;
}
}
in.endObject();
return user;
}
}
然后,在創建Retrofit實例時,使用自定義的TypeAdapter
:
Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserTypeAdapter())
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Retrofit可以與RxJava集成,使得網絡請求的處理更加簡潔和靈活。首先,添加RxJava的依賴:
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
然后,在接口方法中返回Observable
或Single
:
@GET("users/{id}")
Single<User> getUser(@Path("id") int userId);
在發起請求時,可以使用RxJava的操作符來處理響應:
apiService.getUser(1)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<User>() {
@Override
public void onSubscribe(Disposable d) {
// 處理訂閱
}
@Override
public void onSuccess(User user) {
// 處理用戶信息
}
@Override
public void onError(Throwable e) {
// 處理錯誤
}
});
Retrofit基于OkHttp,因此可以使用OkHttp的攔截器來攔截和修改請求或響應。例如,我們可以添加一個日志攔截器來記錄請求和響應的詳細信息:
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
在網絡請求過程中,可能會遇到各種錯誤,如網絡不可用、服務器錯誤等。我們可以在onFailure
回調中處理這些錯誤:
@Override
public void onFailure(Call<User> call, Throwable t) {
if (t instanceof IOException) {
// 網絡錯誤
} else if (t instanceof HttpException) {
// HTTP錯誤
} else {
// 其他錯誤
}
}
可以通過配置OkHttp來設置連接、讀取和寫入的超時時間:
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.build();
可以通過配置OkHttp來啟用緩存:
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(getCacheDir(), cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();
在某些情況下,可能需要處理SSL/TLS證書問題??梢酝ㄟ^配置OkHttp來信任所有證書或自定義證書:
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
.hostnameVerifier((hostname, session) -> true)
.build();
為了保持代碼的清晰和可維護性,建議將Retrofit相關的代碼組織在一個單獨的模塊或包中。例如:
- network
- ApiService.java
- RetrofitClient.java
- models
- User.java
建議在onFailure
回調中統一處理網絡錯誤,并根據錯誤類型進行不同的處理。例如,可以顯示錯誤提示、重試請求等。
Retrofit是一個功能強大且易于使用的HTTP客戶端庫,適用于Android和Java開發。通過本文的介紹,你應該已經掌握了Retrofit的基本使用方法和一些高級技巧。在實際開發中,合理使用Retrofit可以大大提高網絡請求的效率和代碼的可維護性。希望本文對你有所幫助,祝你在Android開發中取得更大的成功!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。