Kevin Learn RecyclerView--> Retrofit + RxJava + OkHttp 网络请求

Posted Kevin_小飞象

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kevin Learn RecyclerView--> Retrofit + RxJava + OkHttp 网络请求相关的知识,希望对你有一定的参考价值。

简介

  • Retrofit 是 Square 公司开发的一款正对 android 网络请求的框架。底层基于 OkHttp 实现,OkHttp 已经得到了 google 官方的认可。

  • OkHttp 也是 Square 开源的网络请求库

  • RxJava 在 GitHub 主页上的自我介绍是 " a library for composing asynchronous and event-based programs using observable sequences for the Java VM "(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava ,概括得非常精准。总之就是让异步操作变得非常简单。

职责:Retrofit 负责请求的数据和请求的结果,使用接口的方式呈现,OkHttp 负责请求的过程,RxJava 负责异步,各种线程之间的切换。

RxJava + Retrofit + okHttp 已成为当前 Android 网络请求最流行的方式。

网络请求

1. 在 app/build.gradle 中添加依赖

	implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.google.code.gson:gson:2.8.9'
    implementation 'io.reactivex:rxjava:1.2.1'
    implementation 'io.reactivex:rxandroid:1.2.1'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
    implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

2. 创建一个统一生成接口实例的管理类

/**
 * Created on 2022/3/18 10:33
 *
 * @author Gong Youqiang
 */
public class RetrofitServiceManager 
    private static final int DEFAULT_TIME_OUT = 5;//超时时间 5s
    private static final int DEFAULT_READ_TIME_OUT = 10;
    private Retrofit mRetrofit;
    private RetrofitServiceManager()
        // 创建 OKHttpClient
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
        builder.writeTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS);//写操作 超时时间
        builder.readTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS);//读操作超时时间

        // 添加公共参数拦截器
        HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
                .addHeaderParams("paltform","android")
                .addHeaderParams("userToken","1234343434dfdfd3434")
                .addHeaderParams("userId","123445")
                .build();
        builder.addInterceptor(commonInterceptor);


        // 创建Retrofit
        mRetrofit = new Retrofit.Builder()
                .client(builder.build())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(Constants.BASE_URL)
                .build();
    

    private static class SingletonHolder
        private static final RetrofitServiceManager INSTANCE = new RetrofitServiceManager();
    

    /**
     * 获取RetrofitServiceManager
     * @return
     */
    public static RetrofitServiceManager getInstance()
        return SingletonHolder.INSTANCE;
    

    /**
     * 获取对应的Service
     * @param service Service 的 class
     * @param <T>
     * @return
     */
    public <T> T create(Class<T> service)
        return mRetrofit.create(service);
    

说明:创建了一个RetrofitServiceManager类,该类采用单例模式,在私有的构造方法中,生成了Retrofit 实例,并配置了OkHttpClient和一些公共配置。提供了一个create()方法,生成接口实例,接收Class范型,因此项目中所有的接口实例Service都可以用这个来生成,代码如下:

mGankService = RetrofitServiceManager.getInstance().create(GankService.class);

3. 网络请求结果基类

/**
 * Created on 2022/3/18 10:26
 * 网络请求结果基类
 * @author Gong Youqiang
 */
public class BaseResponse<T> 
    public int status;
    public String message;

    public T data;

    public boolean isSuccess()
        return status == 200;
    

4. 创建一个业务 ObjectLoader

/**
 * Created on 2022/3/18 10:31
 * 将一些重复的操作提出来,放到父类以免Loader 里每个接口都有重复代码
 * @author Gong Youqiang
 */
public class ObjectLoader 
    /**
     *
     * @param observable
     * @param <T>
     * @return
     */
    protected  <T> Observable<T> observe(Observable<T> observable)
        return observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    

5. 拦截器

/**
 * Created on 2022/3/18 10:30
 * 拦截器
 * @author Gong Youqiang
 */
public class HttpCommonInterceptor implements Interceptor 
    private Map<String,String> mHeaderParamsMap = new HashMap<>();
    public HttpCommonInterceptor() 

    

    @Override
    public Response intercept(Chain chain) throws IOException 
        Log.d("HttpCommonInterceptor","add common params");
        Request oldRequest = chain.request();

        // 新的请求

        Request.Builder requestBuilder =  oldRequest.newBuilder();
        requestBuilder.method(oldRequest.method(), oldRequest.body());
        //添加公共参数,添加到header中
        if(mHeaderParamsMap.size() > 0)
            for(Map.Entry<String,String> params:mHeaderParamsMap.entrySet())
                requestBuilder.header(params.getKey(),params.getValue());
            
        

        Request newRequest = requestBuilder.build();

        return chain.proceed(newRequest);
    

    public static class Builder
        HttpCommonInterceptor mHttpCommonInterceptor;

        public Builder()
            mHttpCommonInterceptor = new HttpCommonInterceptor();
        

        public Builder addHeaderParams(String key, String value)
            mHttpCommonInterceptor.mHeaderParamsMap.put(key,value);
            return this;
        

        public Builder  addHeaderParams(String key, int value)
            return addHeaderParams(key, String.valueOf(value));
        

        public Builder  addHeaderParams(String key, float value)
            return addHeaderParams(key, String.valueOf(value));
        

        public Builder  addHeaderParams(String key, long value)
            return addHeaderParams(key, String.valueOf(value));
        

        public Builder  addHeaderParams(String key, double value)
            return addHeaderParams(key, String.valueOf(value));
        


        public HttpCommonInterceptor build()
            return mHttpCommonInterceptor;
        
    

6. PayLoad.java

/**
 * Created on 2022/3/18 10:32
 *
 * @author Gong Youqiang
 */
public class PayLoad<T> implements Func1<BaseResponse<T>,T> 
    @Override
    public T call(BaseResponse<T> tBaseResponse) //获取数据失败时,包装一个Fault 抛给上层处理错误
        if(!tBaseResponse.isSuccess())
            throw new Fault(tBaseResponse.status,tBaseResponse.message);
        
        return tBaseResponse.data;
    

7. 异常处理类

/**
 * Created on 2022/3/18 10:29
 * 异常处理类,将异常包装成一个 Fault ,抛给上层统一处理
 * @author Gong Youqiang
 */
public class Fault extends RuntimeException 
    private int errorCode;

    public Fault(int errorCode,String message)
        super(message);
        errorCode = errorCode;
    

    public int getErrorCode() 
        return errorCode;
    

8. BasicParamsInterceptor.java

/**
 * Created on 2022/3/18 10:27
 *
 * @author Gong Youqiang
 */
public class BasicParamsInterceptor implements Interceptor 
    Map<String, String> queryParamsMap = new HashMap<>();
    Map<String, String> paramsMap = new HashMap<>();
    Map<String, String> headerParamsMap = new HashMap<>();
    List<String> headerLinesList = new ArrayList<>();

    private BasicParamsInterceptor() 

    

    @Override
    public Response intercept(Chain chain) throws IOException 

        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();

        // process header params inject
        Headers.Builder headerBuilder = request.headers().newBuilder();
        if (headerParamsMap.size() > 0) 
            Iterator iterator = headerParamsMap.entrySet().iterator();
            while (iterator.hasNext()) 
                Map.Entry entry = (Map.Entry) iterator.next();
                headerBuilder.add((String) entry.getKey(), (String) entry.getValue());
            
        

        if (headerLinesList.size() > 0) 
            for (String line: headerLinesList) 
                headerBuilder.add(line);
            
            requestBuilder.headers(headerBuilder.build());
        
        // process header params end


        // process queryParams inject whatever it's GET or POST
        if (queryParamsMap.size() > 0) 
            request = injectParamsIntoUrl(request.url().newBuilder(), requestBuilder, queryParamsMap);
        

        // process post body inject
        if (paramsMap.size() > 0) 
            if (canInjectIntoBody(request)) 
                FormBody.Builder formBodyBuilder = new FormBody.Builder();
                for(Map.Entry<String, String> entry : paramsMap.entrySet()) 
                    formBodyBuilder.add((String) entry.getKey(), (String) entry.getValue());
                

                RequestBody formBody = formBodyBuilder.build();
                String postBodyString = bodyToString(request.body());
                postBodyString += ((postBodyString.length() > 0) ? "&" : "") +  bodyToString(formBody);
                requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString));
            
        

        request = requestBuilder.build();
        return chain.proceed(request);
    
    private boolean canInjectIntoBody(Request request) 
        if (request == null) 
            return false;
        
        if (!TextUtils.equals(request.method(), "POST")) 
            return false;
        
        RequestBody body = request.body();
        if (body == null) 
            return false;
        
        MediaType mediaType = body.contentType();
        if (mediaType == null) 
            return false;
        
        if (!TextUtils.equals(mediaType.subtype(), "x-www-form-urlencoded")) 
            return false;
        
        return true;
    

    // func to inject params into url
    private Request injectParamsIntoUrl(HttpUrl.Builder httpUrlBuilder, Request.Builder requestBuilder, Map<String, String> paramsMap) 
        if (paramsMap.size() > 0) 
            Iterator iterator = paramsMap.entrySet().iterator();
            while (iterator.hasNext()) 
                Map.Entry entry = (Map.Entry) iterator.next();
                httpUrlBuilder.addQueryParameter((String) entry.getKey(), (String) entry.getValue());
            
            requestBuilder.url(httpUrlBuilder.build());
            return requestBuilder.build();
        

        return null;
    

    private static String bodyToString(final RequestBody request)
        try 
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            if(copy != null)
                copy.writeTo(buffer);
            else
                return "";
            return buffer.readUtf8();
        
        catch (final IOException e) 
            return "did not work";
        
    

    public static class Builder 

        BasicParamsInterceptor interceptor;

        public Builder() 
            interceptor = new BasicParamsInterceptor();
        

        public Builder addParam(String key, String value) 
            interceptor.paramsMap.put(key, value);
            return this;
        

        public Builder addParamsMap(Map<String, String> paramsMap) 
            interceptor.paramsMap.putAll(paramsMap);
            return this;
        

        public Builder addHeaderParam(String key, String value) 
            interceptor.headerParamsMap.put(key, value);
            return this;
        

        public Builder addHeaderParamsMap(Map<String, String> headerParamsMap) 
            interceptor.headerParamsMap.putAll(headerParamsMap);
            return this;
        

        public Builder addHeaderLine(String headerLine) 
            int index = headerLine.indexOf(":");
            if (index == -1) 
                throw new IllegalArgumentException("Unexpected header: " + headerLine);
            
            interceptor.headerLinesList.add(headerLine);
            return this;
        

        public Builder addHeaderLinesList(List<String> headerLinesList) 
            for (String headerLine: headerLinesList) 
                int index = headerLine.indexOf(":");
                if (index == -1) 
                    throw new IllegalArgumentException("Unexpected header: " + headerLine);
                
                interceptor.headerLinesList以上是关于Kevin Learn RecyclerView--> Retrofit + RxJava + OkHttp 网络请求的主要内容,如果未能解决你的问题,请参考以下文章

Kevin Learn RecyclerView--> 实现二级列表

Kevin Learn Recyclerview-->Leanback 中的 HorizontalGridView

Kevin Learn Recyclerview-->UltimateRecyclerView 的基本使用

Kevin Learn RecyclerView--> Retrofit + RxJava + OkHttp 网络请求

Kevin Learn Recyclerview-->SpringView (下拉刷新)的基本使用

Kevin Learn Kotlin:函数