Retrofit本身并不支持网络通讯。

Retrofit封装了OkHttp,让网络请求更加简单。

Retrofit通过接口+注解的方式,封装了重复的代码。

封装了Gson,可以直接将返回的json字符串转换成Java对象

结合rxjava,实现响应式编程

使用Retrofit进行网络通讯就好像使用SpringCloud中的Openfeign

官网地址:https://square.github.io/retrofit/

使用步骤

准备

1、在build.gradle中引入依赖implementation 'com.squareup.retrofit2:retrofit:2.9.0'

2、在AndroidManifest.xml中添加网络请求权限

一、简单使用

使用 https://www.httpbin.org/ 作为我们的测试接口地址

1、创建接口类

@POST 声明为post请求,实际请求地址会拼接成 https://www.httpbin.org/post, 通过@FormUrlEncoded和@Field声明表单请求参数;@Body声明Body参数。

@GET 声音为get请求,实际请求地址会拼接成 https://www.httpbin.org/get, 通过@Query声明请求参数。

import okhttp3.RequestBody;

import okhttp3.ResponseBody;

import retrofit2.Call;

import retrofit2.http.Body;

import retrofit2.http.Field;

import retrofit2.http.FormUrlEncoded;

import retrofit2.http.GET;

import retrofit2.http.POST;

import retrofit2.http.Query;

public interface HttpbinService {

@POST("post")

@FormUrlEncoded

Call post(@Field("username") String username, @Field("password") String pwd);

@GET("get")

Call get(@Query("username") String username,@Query("password") String pwd);

@POST("post")

Call postBody(@Body RequestBody requestBody);

}

2、在Android程序中使用

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import java.io.IOException;

import okhttp3.ResponseBody;

import retrofit2.Call;

import retrofit2.Callback;

import retrofit2.Retrofit;

public class MainActivity extends AppCompatActivity {

private Retrofit retrofit;

private HttpbinService httpbinService;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org/").build();

httpbinService = retrofit.create(HttpbinService.class);

}

/**

* 异步Get请求

*/

public void getAsync(View view) {

Call resp = httpbinService.get("test", "123123");

resp.enqueue(new Callback() {

@Override

public void onResponse(Call call, retrofit2.Response response) {

try {

Log.d("test", "getAsync: " + response.body().string());

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void onFailure(Call call, Throwable t) {

Log.d("test", "getAsync error: " + t.getMessage());

}

});

}

/**

* 异步Post请求

*/

public void postAsync(View view) {

Call resp = httpbinService.post("test", "123123");

resp.enqueue(new Callback() {

@Override

public void onResponse(Call call, retrofit2.Response response) {

try {

Log.d("test", "postAsync: " + response.body().string());

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void onFailure(Call call, Throwable t) {

Log.d("test", "postAsync error: " + t.getMessage());

}

});

}

}

二、配合Gson 以及 Rxjava,返回java对象和响应式编程

在build.gradle中引入依赖

implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'

本例中使用 https://www.wanandroid.com/ 测试接口调用

1、添加测试接口类

import io.reactivex.rxjava3.core.Flowable;

import okhttp3.ResponseBody;

import retrofit2.Call;

import retrofit2.http.Field;

import retrofit2.http.FormUrlEncoded;

import retrofit2.http.GET;

import retrofit2.http.POST;

import retrofit2.http.Path;

public interface WanAndroidTestService {

/**正常返回 Java对象 */

@POST("/user/login")

@FormUrlEncoded

Call login(@Field("username") String username, @Field("password") String password);

/**通过RxJava响应式返回 Java对象 */

@POST("/user/login")

@FormUrlEncoded

Flowable login2(@Field("username") String username, @Field("password") String password);

/**通过RxJava响应式返回 ResponseBody */

@GET("lg/collect/list/{pageNum}/json")

Flowable getArticle(@Path("pageNum") int pageNum);

}

2、测试使用,返回Java对象

添加转换器 addConverterFactory(GsonConverterFactory.create())

public class WanAndroidUnitTest {

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wanandroid.com/")

.addConverterFactory(GsonConverterFactory.create())//添加转换器

.build();

WanAndroidTestService wanAndroidService = retrofit.create(WanAndroidTestService.class);

@Test

public void login() throws IOException {

Response response = wanAndroidService.login("xxxxx", "xxxxx").execute();

LoginUser loginUser = response.body();

System.out.println("loginUser = " + loginUser);

}

}

3、配合RxJava使用,并使用cookie

添加Cookie支持 添加Gson转换器addConverterFactory(GsonConverterFactory.create()) 添加RxJava适配器addCallAdapterFactory(RxJava3CallAdapterFactory.create())

本示例代码使用www.wanandroid.com的开放接口,可以自行去注册一个账号用于测试

import io.reactivex.rxjava3.functions.Consumer;

import io.reactivex.rxjava3.functions.Function;

import io.reactivex.rxjava3.schedulers.Schedulers;

import okhttp3.Cookie;

import okhttp3.CookieJar;

import okhttp3.HttpUrl;

import okhttp3.OkHttpClient;

import okhttp3.ResponseBody;

import retrofit2.Retrofit;

import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;

import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitCookieUnitTest {

Map> cookies = new HashMap<>();

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wanandroid.com/")

// 添加Cookie支持

.callFactory(new OkHttpClient.Builder().cookieJar(new CookieJar() {

@Override

public void saveFromResponse(HttpUrl url, List list) {

cookies.put(url.host(), list);

}

@Override

public List loadForRequest(HttpUrl url) {

List list = cookies.get(url.host());

return list == null ? new ArrayList<>() : list;

}

}).build())

//添加Gson转换器

.addConverterFactory(GsonConverterFactory.create())

//添加RxJava适配器

.addCallAdapterFactory(RxJava3CallAdapterFactory.create())

.build();

WanAndroidTestService androidTestService = retrofit.create(WanAndroidTestService.class);

@Test

public void rxTest() throws IOException {

androidTestService.login2("xxxxx", "xxxxx")

// 登录成功后,执行下一步操作,查询收藏文章列表

.flatMap(new Function>() {

@Override

public Publisher apply(LoginUser loginUser) throws Throwable {

return androidTestService.getArticle(0);

}

})

.observeOn(Schedulers.io())

// 如果是Android环境需要切换到Android的主线程

// .subscribeOn(AndroidSchedulers.mainThread())

// 这里是Junit,切换到新的线程

.subscribeOn(Schedulers.newThread())

// 订阅返回结果,并打印输出

.subscribe(new Consumer() {

@Override

public void accept(ResponseBody responseBody) throws Throwable {

System.out.println(responseBody.string());

}

});

while (true) {

}

}

}

4、文件上传、下载

文件上传

使用注解@Multipart和@Part实现文件上传

1)创建请求接口

import okhttp3.MultipartBody;

import okhttp3.ResponseBody;

import retrofit2.Call;

import retrofit2.http.Multipart;

import retrofit2.http.POST;

import retrofit2.http.Part;

public interface UploadFileService {

@POST("post")

@Multipart

Call upload(@Part MultipartBody.Part part);

}

2)编写测试代码

public class UploadFileTest {

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org/").build();

UploadFileService uploadFileService = retrofit.create(UploadFileService.class);

@Test

public void upload() throws IOException {

File file1 = new File("d:/temp/1.txt");

MultipartBody.Part part = MultipartBody.Part.createFormData("file1", file1.getName(),

RequestBody.create(MediaType.parse("text/plain"), file1));

Call resp = uploadFileService.upload(part);

System.out.println("resp = " + resp.execute().body().string());

}

}

文件下载

Call 常规下载Flowable 通过RxJava方式下载,需要添加RxJava适配器

如果下载的文件很大,需要增加注解 @Streaming避免出现内存溢出

1)创建请求接口

import io.reactivex.rxjava3.core.Flowable;

import okhttp3.MultipartBody;

import okhttp3.ResponseBody;

import retrofit2.Call;

import retrofit2.http.GET;

import retrofit2.http.Multipart;

import retrofit2.http.POST;

import retrofit2.http.Part;

import retrofit2.http.Streaming;

import retrofit2.http.Url;

public interface UploadFileService {

@POST("post")

@Multipart

Call upload(@Part MultipartBody.Part part);

@GET

Call download(@Url String url);

@Streaming

@GET

Flowable downloadRxJava(@Url String url);

}

2)创建测试用例

import org.junit.Test;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import io.reactivex.rxjava3.functions.Consumer;

import io.reactivex.rxjava3.functions.Function;

import okhttp3.ResponseBody;

import retrofit2.Response;

import retrofit2.Retrofit;

import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;

public class DownloadFileTest {

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org/")

//添加RxJava适配器

.addCallAdapterFactory(RxJava3CallAdapterFactory.create())

.build();

UploadFileService uploadFileService = retrofit.create(UploadFileService.class);

@Test

public void download() throws IOException {

Response response = uploadFileService.download("https://www.dasouji.com/wp-content/uploads/2020/12/@ukwanghyun.jpg")

.execute();

if (!response.isSuccessful()) {

System.out.println("下载失败," + response.code());

return;

}

InputStream inputStream = response.body().byteStream();

FileOutputStream fos = new FileOutputStream("d:/temp/3.jpg");

int len;

byte[] buffer = new byte[4096];

while ((len = inputStream.read(buffer)) != -1) {

fos.write(buffer, 0, len);

}

fos.close();

inputStream.close();

System.out.println("下载完成," + response.code());

}

@Test

public void downloadRxJava() throws IOException {

uploadFileService.downloadRxJava("https://www.dasouji.com/wp-content/uploads/2020/12/@ukwanghyun.jpg")

// 将结果映射成File对象

.map(new Function() {

@Override

public File apply(ResponseBody responseBody) throws Throwable {

InputStream inputStream = responseBody.byteStream();

File file = new File("d:/temp/4.jpg");

FileOutputStream fos = new FileOutputStream(file);

int len;

byte[] buffer = new byte[4096];

while ((len = inputStream.read(buffer)) != -1) {

fos.write(buffer, 0, len);

}

fos.close();

inputStream.close();

System.out.println("下载完成!");

return file;

}

})

// 获取下载结果

.subscribe(new Consumer() {

@Override

public void accept(File file) throws Throwable {

System.out.println("获取下载文件!" + file.getName());

}

});

while (true) {

}

}

}

Retrofit的注解

方法注解:@GET,@POST,@PUT,@DELETE,@PATH,@HEAD,@OPTIONS,@HTTP标记注解:@FormUrlEncoded,@Multipart,@Streaming参数注解:@Query,@Field,@Body,@FieldMap,@QueryMap,@Part,@PartMap其他注解:@Path,@Header,@Headers,@Url

查看原文