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中添加网络请求权限<uses-permission android:name="android.permission.INTERNET"/>
一、简单使用
使用 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<ResponseBody> post(@Field("username") String username, @Field("password")  String pwd);
    @GET("get")
    Call<ResponseBody> get(@Query("username") String username,@Query("password")  String pwd);
    @POST("post")
    Call<ResponseBody> 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<ResponseBody> resp = httpbinService.get("test", "123123");
        resp.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                try {
                    Log.d("test", "getAsync: " + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.d("test", "getAsync error: " + t.getMessage());
            }
        });
    }
    /**
     * 异步Post请求
     */
    public void postAsync(View view) {
        Call<ResponseBody> resp = httpbinService.post("test", "123123");
        resp.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                try {
                    Log.d("test", "postAsync: " + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Call<ResponseBody> 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<LoginUser> login(@Field("username") String username, @Field("password") String password);
    /**通过RxJava响应式返回 Java对象 */
    @POST("/user/login")
    @FormUrlEncoded
    Flowable<LoginUser> login2(@Field("username") String username, @Field("password") String password);
    /**通过RxJava响应式返回 ResponseBody */
    @GET("lg/collect/list/{pageNum}/json")
    Flowable<ResponseBody> 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<LoginUser> 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())
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<String, List<Cookie>> 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<Cookie> list) {
                    cookies.put(url.host(), list);
                }
                @Override
                public List<Cookie> loadForRequest(HttpUrl url) {
                    List<Cookie> 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<LoginUser, Publisher<ResponseBody>>() {
                    @Override
                    public Publisher<ResponseBody> apply(LoginUser loginUser) throws Throwable {
                        return androidTestService.getArticle(0);
                    }
                })
                .observeOn(Schedulers.io())
                // 如果是Android环境需要切换到Android的主线程
                // .subscribeOn(AndroidSchedulers.mainThread())
                // 这里是Junit,切换到新的线程
                .subscribeOn(Schedulers.newThread())
                // 订阅返回结果,并打印输出
                .subscribe(new Consumer<ResponseBody>() {
                    @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<ResponseBody> 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<ResponseBody> resp = uploadFileService.upload(part);
        System.out.println("resp = " + resp.execute().body().string());
    }
}
文件下载
- Call 常规下载
- Flowable 通过RxJava方式下载,需要添加RxJava适配器
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<ResponseBody> upload(@Part MultipartBody.Part part);
    @GET
    Call<ResponseBody> download(@Url String url);
    @Streaming
    @GET
    Flowable<ResponseBody> 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<ResponseBody> 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<ResponseBody, File>() {
                    @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<File>() {
                    @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










