OkHttp与Reftrofit2

一.前言

越来越多的人使用okhttp作为自己的网络访问框架,okhttp与Reftrofit的结合也是很多人喜欢用的.本文就OkHttp与Reftrofit2与RxJava的结合使用的小demo介绍这三者的联合使用.

二.okhttp

1.引入库文件

    compile 'com.squareup.okhttp:okhttp:2.4.0'
    compile 'com.squareup.okio:okio:1.5.0'

注意:okhttp内部依赖okio,别忘了引入.

2.get请求

其实单纯使用okhttp的网络请求和我们常用的volley等还是挺像的.没什么难度.

//    使用ohhttp访问网络
    public void get(String url, Callback callback) {
        //创建okHttpClient对象
        OkHttpClient mOkHttpClient = new OkHttpClient();
        //创建一个Request
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        //new call
        Call call = mOkHttpClient.newCall(request);
        //请求加入调度
        call.enqueue(callback);
    }

调用

        get("http://apis.baidu.com/heweather/pro/attractions", new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                CustomToast.showToast(e.toString());
            }

            @Override
            public void onResponse(Response response) throws IOException {
                CustomToast.showToast(response.body().string());
            }

        });

3.post请求

    public void post(String url,Callback callback){
        //创建okHttpClient对象
        OkHttpClient mOkHttpClient = new OkHttpClient();
        FormEncodingBuilder builder = new FormEncodingBuilder();
        builder.add("username","king");
        Request request = new Request.Builder()
                .url(url)
                .post(builder.build())
                .build();
        mOkHttpClient.newCall(request).enqueue(callback);

    }

调用

        post("https://github.com/hongyangAndroid", new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {a
                CustomToast.showToast(e.toString());
            }

            @Override
            public void onResponse(Response response) throws IOException {
                CustomToast.showToast(response.body().string());
            }
        });

4.其他

1.这里只介绍okhttp的基础使用,像文件上传下载和对其二次封装就不过多的说了.具体可以看下这篇文章
http://blog.csdn.net/lmj623565791/article/details/47911083

2.这里request请求用了Request.Builder这样一个方法.这其实就是一个建造者模式的应用,我们在使用alert的时候也见过这样的代码

AlertDialog.Builder builder=new AlertDialog.Builder(this);

具体可以看我写的另一篇博客
android常用的设计模式总结

大家翻一下源码很容易看明白的,核心代码就这一点

public final class Request {
private Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tag = builder.tag != null ? builder.tag : this;
  }
    public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }
    }

二.reftrofit2

1.介绍

你可以把reftrofit2理解为是一个基于okhttp的网络访问工具类.
和我们常用的工具类不同的是,Retrofit的解耦更彻底:例如通过注解来配置请求参数,根据需求来选择使用不同的CallAdapter(请求适配器,如:RxJava,Java8, Guava)、Converter(反序列化工具,如json, protobuff, xml, moshi)等。

2.基本使用

(1)引入库文件

//retrofit jar
compile 'com.squareup.retrofit2:retrofit:2.0.2'
//反序列化json工具
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

(2)get请求

先定义一个接口

public interface APIService {
    @GET("weather")
    Call<Weather> loadeather(@Query("cityname") String cityname,@Query("key") String apiKey);
    }

在这里loadeather()方法就是就被标记成了get方法,请求的地址就baseurl+wather.请求参数为cityname和key

看一下调用

    Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        APIService service = retrofit.create(APIService.class);
        service.loadeather("杭州", apiKey).enqueue(new Callback<Weather>() {
            @Override
            public void onResponse(Response<Weather> response, Retrofit retrofit) {
                if (response.body() != null) {
                    Weather weather = response.body();
                    if (weather.getResult() != null) {
                         //xxx
                    } else {
                        tv.setText(weather.getReason());
                    }
                } else {
                    tv.setText("onResponse: body==null");
                }
            }

            @Override
            public void onFailure(Throwable t) {
                tv.setText(t.toString());
            }
        });

这里
.addConverterFactory(GsonConverterFactory.create())
这句话就是把返回结果的json转换成了对象

(3)post请求

同样先定义一个接口

public interface APIUserService {
    @FormUrlEncoded
    @POST("Login")
    Call<UserInfo> login(
            @Field("userName") String userName,
            @Field("password") String password,
            @Field("clubId") int clubId,
            @Field("leagueId") int leagueId
            );
}

@FormUrlEncoded代表 表单的方式传递键值对
发送的请求是键值对的形式.

不过我们经常发送的请求是json类型的,怎么发送这样的请求呢?

public interface APIUserService {
    @POST("Login")
    @Headers({"Content-Type: application/json","Accept: application/json"})//需要添加头
    Call<UserInfo> login(@Body RequestBody body);

}

发送post请求

      String url = "http://106.75.xx.xx:8080/Api/Front/";
        Retrofit retrofit = new Retrofit.Builder().baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        APIUserService service = retrofit.create(APIUserService.class);
        JSONObject result = new JSONObject();
        try {
           result.put("userName","admin");
           result.put("password","xxxx");
           result.put("clubId",1);
           result.put("leagueId",2);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        HashMap map = new HashMap();

        RequestBody body = RequestBody.create(MediaType.parse("application/json"), result.toString());
        service.login(body).enqueue(new Callback<UserInfo>() {
            @Override
            public void onResponse(Response<UserInfo> response, Retrofit retrofit) {
                if (response!=null) {
                    UserInfo body = response.body();
                    tv.setText(body.toString());
                }
            }

            @Override
            public void onFailure(Throwable t) {
                tv.setText(t.toString());
            }
        });

设置Interceptor
这个需要简单提一下,很多时候,比如你使用retrofit需要统一的log管理,给每个请求添加统一的header等,这些都应该通过okhttpclient去操作,比如addInterceptor
这里给大家看一个比较全的设置

package com.ethanco.retrofit2_0test;

import java.io.File;
import java.io.IOException;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;

/**
 * Created by king on 2017/3/26.
 */

public class AppClient {
    public static Retrofit retrofit = null;
    public static Retrofit retrofit() {
        if (retrofit == null) {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            //设置缓存,代码略
            setCache(builder);
           // 公共参数,代码略
            setComent(builder);
            // 设置头,代码略
            setHeader(builder);
           //Log信息拦截器,代码略
            setLog(builder);
            //设置cookie,代码略
            setCookie(builder);
            //设置超时和重连,代码略
            setConnect(builder);
            //以上设置结束,才能build(),不然设置白搭
            OkHttpClient okHttpClient = builder.build();
            retrofit = new Retrofit.Builder()
                    .baseUrl("192.168.1.101")
                    .client(okHttpClient)
                    .build();
        }
        return retrofit;
    }

    private static void setCookie(OkHttpClient.Builder builder) {
        /**
         * 设置cookie
         */
        CookieManager cookieManager = new CookieManager();
        cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        builder.cookieJar(new CookieJar() {
            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {

            }

            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                return null;
            }
        });
    }

    private static void setHeader(OkHttpClient.Builder builder) {
        /**
         * 设置头
         */
        Interceptor headerInterceptor = new Interceptor() {

            @Override
            public Response intercept(Chain chain) throws IOException {
                Request orignaRequest = chain.request();
                Request request = orignaRequest.newBuilder()
                        .header("AppType", "TPOS")
                        .header("Content-Type", "application/json")
                        .header("Accept", "application/json")
                        .method(orignaRequest.method(), orignaRequest.body())
                        .build();

                return chain.proceed(request);
            }
        };
        builder.addInterceptor(headerInterceptor);
    }

    private static void setComent(OkHttpClient.Builder builder) {
        /**
         * 公共参数
         */
        Interceptor addQueryParameterInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request originalRequest = chain.request();
                Request request;
                String method = originalRequest.method();
                Headers headers = originalRequest.headers();
                HttpUrl modifiedUrl = originalRequest.url().newBuilder()
                        // Provide your custom parameter here
                        .addQueryParameter("platform", "adnroid")
                        .addQueryParameter("version", "1.2.0")
                        .build();
                request = originalRequest.newBuilder().url(modifiedUrl).build();
                return chain.proceed(request);
            }
        };
        //公共参数
        builder.addInterceptor(addQueryParameterInterceptor);
    }

    private static void setCache(OkHttpClient.Builder builder) {
        final File chachefile = new File(BaseApplication.getContext().getExternalCacheDir(), "HttpCache");
        final Cache cache = new Cache(chachefile, 1024 * 1024 * 50);//缓存文件
        Interceptor cacheInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!NetWorkUtils.isNetworkConnected(BaseApplication.getContext())) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
                Response response = chain.proceed(request);
                if (NetWorkUtils.isNetworkConnected (BaseApplication.getContext())) {
                    int maxAge = 0;

                    // 有网络时 设置缓存超时时间0个小时
                    response.newBuilder()
                            .header("Cache-Control", "public, max-age=" + maxAge)
                            .removeHeader("Pragma")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
                            .build();
                } else {
                    //无网络时,设置超时为4周
                    int maxStale = 60 * 60 * 24 * 28;
                    response.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            .removeHeader("Pragma")
                            .build();
                }

                return response;
            }
        };
        builder.cache(cache).addInterceptor(cacheInterceptor);
    }

    public static void setConnect(OkHttpClient.Builder builder) {
        /**
         * 设置超时和重连
         */
        //设置超时
        builder.connectTimeout(15, TimeUnit.SECONDS);
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        //错误重连
        builder.retryOnConnectionFailure(true);
    }

    public static void setLog(OkHttpClient.Builder builder) {
        /**
         * log信息拦截器
         */
        if (BuildConfig.DEBUG) {
            //log信息拦截器
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            //设置Debug Log模式
            builder.addInterceptor(httpLoggingInterceptor);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/jin870132/article/details/66474800