Retrofit是一个流行的网络请求框架,可以将声明的网络请求接口通过动态代理的方式生成具体的请求,内部实际使用OkHttp进行网络请求,可以使用Gson处理请求的数据,使用RxJava进行线程的切换。下面从基础的Retrofit请求开始,依次添加OkHttp配置、Gson、RxJava简化网络请求。
接口来源:和风天气api, 网络请求key需要自己申请
例子
首先创建一个基础的Retrofit实例:
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://devapi.qweather.com") .build();
然后声明网络请求接口:
public interface QWeatherApi1 { @GET("/v7/weather/now") Call<ResponseBody> queryNow(@Query("key") String key, @Query("location") String location); }
进行网络请求:
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://devapi.qweather.com") .build(); QWeatherApi1 api1 = retrofit.create(QWeatherApi1.class); api1.queryNow(key, "101010100").enqueue(new Callback<ResponseBody>() { @Override public void onResponse(@NotNull Call<ResponseBody> call, @NotNull retrofit2.Response<ResponseBody> response) { try { System.out.println(response.code()); System.out.println("onResponse(" + response.body().string()); //Retrofit内部进行了线程切换, 当前是主线程 System.out.println(Looper.myLooper()); } catch (Exception e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { System.out.println("onFailure(" + t.getMessage()); } });
进行网络请求时需要统一配置超时时间等,同时还需要进行认证(如天气请求时统一的key), 这可以通过添加自定义的OkHttpClient来实现。
OkHttpClient client = new OkHttpClient.Builder() //连接超时时间 .connectTimeout(10, TimeUnit.SECONDS) //读超时时间 .readTimeout(10, TimeUnit.SECONDS) //写超时时间 .writeTimeout(10, TimeUnit.SECONDS) .addInterceptor(new Interceptor() { @NotNull @Override public Response intercept(@NotNull Chain chain) throws IOException { //统一添加接口需要的key RealInterceptorChain realInterceptorChain = (RealInterceptorChain) chain; Request request = realInterceptorChain.request(); HttpUrl.Builder builder = request.url().newBuilder(); builder.addQueryParameter("key", key); return chain.proceed(request.newBuilder().url(builder.build()).build()); } }) .build(); Retrofit retrofit = new Retrofit.Builder().baseUrl("https://devapi.qweather.com") .client(client) .build();
于是网络请求接口可以简化为:
public interface QWeatherApi2 { @GET("/v7/weather/now") Call<ResponseBody> queryNow(@Query("location") String location); }
同样地,如下进行网络请求:
QWeatherApi2 api2 = retrofit.create(QWeatherApi2.class); api2.queryNow("101010100").enqueue( ... );
网络请求回来的数据需要转成model, Retrofit提供了相关接口,可以通过Gson将请求回来的字符串转成model。
添加依赖:
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.google.code.gson:gson:2.8.7'
Retrofit创建时增加解析Factory:
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://devapi.qweather.com") //使用gson进行json到model的转换 .addConverterFactory(GsonConverterFactory.create()) //okhttp进行数据实际请求 .client(client) .build();
网络请求接口可以写成:
public interface QWeatherApi3 { @GET("/v7/weather/now") Call<NowWeatherResponse> queryNow(@Query("location") String location); }
于是网络请求如下:
QWeatherApi3 api3 = retrofit.create(QWeatherApi3.class); api3.queryNow("101010100").enqueue(new Callback<NowWeatherResponse>() { @Override public void onResponse(Call<NowWeatherResponse> call, retrofit2.Response<NowWeatherResponse> response) { System.out.println(response.body()); } @Override public void onFailure(Call<NowWeatherResponse> call, Throwable t) { System.out.println("onFailure(" + t.getMessage()); } });
如果需要对返回的数据进一步处理,那么使用RxJava是一个比较好的选择。RxJava能够方便的进行上下文切换,可以将复杂、耗时的操作放到非主线程中执行,然后在主线程返回结果。
引入RxJava依赖:
implementation 'io.reactivex.rxjava2:rxjava:2.2.7' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation "com.squareup.retrofit2:adapter-rxjava2:2.9.0"
将RxJava配置到Retrofit中:
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://devapi.qweather.com") //使用gson进行json到model的转换 .addConverterFactory(GsonConverterFactory.create()) //使用rxjava管理数据的处理与线程切换 .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //okhttp进行数据实际请求 .client(client) .build();
然后修改网络请求接口声明:
public interface QWeatherApi4 { @GET("/v7/weather/now") Observable<NowWeatherResponse> queryNow(@Query(value = "location") String location); }
于是网络请求如下:
QWeatherApi4 api4 = retrofit.create(QWeatherApi4.class); api4.queryNow("101010100") .map(nowWeatherResponse -> { // 这里是io线程,可以进行复杂耗时的操作 System.out.println("线程:" + Thread.currentThread()); return nowWeatherResponse; }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(nowWeatherResponse -> { // 这里已经是主线程了, System.out.println("线程:" + Thread.currentThread()); return nowWeatherResponse; }) .subscribe(new Observer<NowWeatherResponse>() { @Override public void onSubscribe(@NonNull Disposable d) { list.add(d); } @Override public void onNext(@NonNull NowWeatherResponse weatherResponse) { System.out.println("onNext:" + weatherResponse); System.out.println("onNext(线程:" + Thread.currentThread()); } @Override public void one rror(@NonNull Throwable e) { System.out.println("onError:" + e.getMessage()); e.printStackTrace(); } @Override public void onComplete() { } });