Android--- Retrofit with Okhttp

本文详细介绍了OkHttp的网络请求优化,Retrofit的接口描述与自动调用,以及两者如何结合使用于RxJava实现异步网络操作。通过实例展示如何构建Retrofit Client、定义服务接口和处理响应数据。
摘要由CSDN通过智能技术生成

什么是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

包含:

  1. 封装Token、Header、URL,构建http request
  2. 定义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负责异步,各种线程之间的切换,用起来非常便利

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值