Android--- Retrofit with Okhttp
什么是Okhttp
- OkHttp是一个网络请求框架
Okhttp 样例代码
private void testOkHttp() throws IOException {
//Step1 创建HttpClient对象,也就是构建一个网络类型的实例
final OkHttpClient client = new OkHttpClient();
//Step2 构建Request, 具体的请求url,请求头,请求体等等
final Request request = new Request.Builder()
.url("https://www.google.com.hk").build();
//Step3 构建请求Call,也就是将具体的网络请求与执行请求的实体进行绑定
Call call = client.newCall(request);
//step4 发送网络请求,获取数据,进行后续处理
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG,response.toString());
Log.i(TAG,response.body().string());
}
});
okhttp的优缺点
优点:
- OkHttp主要负责socket部分的优化,比如多路复用,buffer缓存,数据压缩等等
缺点:
- 用户网络请求的接口配置繁琐,尤其是需要配置请求body,请求头,参数的时候
- 数据解析过程需要用户手动拿到responsbody进行解析,不能复用;
- 无法适配自动进行线程的切换
以上缺点可以用Retrofit解决
什么是Retrofit
- 是一个RESTful的HTTP网络请求框架的封装
- Retrofit 通过 java 接口以及注解来描述网络请求,并用动态代理的方式生成网络请求的 request,然后通过 client 调用相应的网络框架(默认 okhttp)去发起网络请求,并将返回的 response 通过 converterFactorty 转换成相应的数据 model,最后通过 calladapter 转换成其他数据方式(如 rxjava Observable)
Retorfit解析
构建RetrofitClient
包含:
- 封装Token、Header、URL,构建http request
- 定义converter (将返回的 response 通过 converterFactorty 转换成相应的数据 model), 以下例子使用GsonConverterFactory可以将json转化成Java Beans
public class RetrofitClient {
private static Retrofit retrofit;
private static final String BASE_URL = "https://api.yelp.com/v3/";
private static final String TOKEN = "RO1Oxxrhr0ZE2nvxEvJ0ViejBTWKcLLhPQ7wg6GGPlGiHvjwaLPU2eWlt4myH3BC1CP4RSzIQ7UCFjZ-FBaF_4ToUYHfs6FF6FwipyMuz47xVvlpEr6gDv-2YRQUYnYx";
public static Retrofit getRetrofit() {
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor(){
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", " Bearer " + TOKEN)
.build();
return chain.proceed(newRequest);
}
}).build();
retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
构建service
package com.example.eatwhat.service;
import com.example.eatwhat.service.BusinessesPojo.DetailedBusiness;
import com.example.eatwhat.service.RestaurantPojo.Restaurant;
import com.example.eatwhat.service.ReviewsPojo.Reviews;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface RestaurantService {
@GET("businesses/{id}")
Call<DetailedBusiness> getRestaurantById(@Path("id") String id);
@GET("businesses/search")
Call<Restaurant> queryRestaurantByCategory(@Query("term") String restaurant,
@Query("location") String location,
@Query("categories") String categories,
@Query("sort_by") String sortBy,
@Query("limit") int limit,
@Query("offset") int offset);
@GET("businesses/{id}/reviews")
Call<Reviews> queryReviewByBusinessID(@Path("id") String id);
}
发起网络请求接收数据
private void initData(){
//创建retrofit对象, 构建一个网络请求的载体对象
RetrofitClient retrofitClient = new RetrofitClient();
//Retrofit的精髓,为统一配置网络请求完成动态代理的设置
RestaurantService methods = retrofitClient.getRetrofit().create(RestaurantService.class);
/*构建具体网络请求对象Request(service),在这个阶段要完成的任务:
1)将接口中的注解翻译成对应的参数;
2)确定网络请求接口的返回值response类型以及对应的转换器;
3)讲Okhttp的Request封装成为Retrofit的OKhttpCall。总结来说,就是根据请求service 的Interface来封装Okhttp请求Request*/
Call<Restaurant> call = methods.queryRestaurantByCategory(inputRestaurantName, selectedCity, selectedCategory, sortBy, limit, offset);
//进行网络请求了,然后处理网络请求的数据了
call.enqueue(new Callback<Restaurant>() {
@Override
public void onResponse(Call<Restaurant> call, Response<Restaurant> response) {
if (response.code() == 200){
//将结果转换成Java bean (Business)
for (Business business: response.body().getBusinesses()){
RestaurantCard restaurantCard = new RestaurantCard(business.getImageUrl(), business.getName(), business.getCategories().get(0).getTitle(), business.getRating(), business.getId());
restaurantCardArrayList.add(restaurantCard);
}
}
else {
Log.d(TAG+ "From onReponse", "code not 200");
}
}
@Override
public void onFailure(Call<Restaurant> call, Throwable t) {
Log.d(TAG+ "From onReponse", "Failed");
}
});
}
Restaurant Bean
public class Restaurant {
@SerializedName("businesses")
@Expose
private List<Business> businesses = null;
@SerializedName("total")
@Expose
private int total;
@SerializedName("region")
@Expose
private Region region;
public List<Business> getBusinesses() {
return businesses;
}
public void setBusinesses(List<Business> businesses) {
this.businesses = businesses;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public Region getRegion() {
return region;
}
public void setRegion(Region region) {
this.region = region;
}
}
Business Bean
public class Business {
@SerializedName("id")
@Expose
private String id;
@SerializedName("alias")
@Expose
private String alias;
@SerializedName("name")
@Expose
private String name;
@SerializedName("image_url")
@Expose
private String imageUrl;
@SerializedName("is_closed")
@Expose
private boolean isClosed;
@SerializedName("url")
@Expose
private String url;
@SerializedName("review_count")
@Expose
private int reviewCount;
@SerializedName("categories")
@Expose
private List<Category> categories = null;
@SerializedName("rating")
@Expose
private float rating;
@SerializedName("coordinates")
@Expose
private Coordinates coordinates;
@SerializedName("transactions")
@Expose
private List<String> transactions = null;
@SerializedName("price")
@Expose
private String price;
@SerializedName("location")
@Expose
private Location location;
@SerializedName("phone")
@Expose
private String phone;
@SerializedName("display_phone")
@Expose
private String displayPhone;
@SerializedName("distance")
@Expose
private float distance;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public boolean isIsClosed() {
return isClosed;
}
public void setIsClosed(boolean isClosed) {
this.isClosed = isClosed;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getReviewCount() {
return reviewCount;
}
public void setReviewCount(int reviewCount) {
this.reviewCount = reviewCount;
}
public List<Category> getCategories() {
return categories;
}
public void setCategories(List<Category> categories) {
this.categories = categories;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
public Coordinates getCoordinates() {
return coordinates;
}
public void setCoordinates(Coordinates coordinates) {
this.coordinates = coordinates;
}
public List<String> getTransactions() {
return transactions;
}
public void setTransactions(List<String> transactions) {
this.transactions = transactions;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getDisplayPhone() {
return displayPhone;
}
public void setDisplayPhone(String displayPhone) {
this.displayPhone = displayPhone;
}
public float getDistance() {
return distance;
}
public void setDistance(float distance) {
this.distance = distance;
}
}
RxJava+Retrofit+OkHttp
- Retrofit负责请求的数据和请求的结果,使用接口的方式呈现,
- OkHttp负责请求的过程
- RxJava负责异步,各种线程之间的切换,用起来非常便利