Android Rxjava+Retrofit网络请求框架封装

版权声明:本文为博主原创文章 && 转载请著名出处https://blog.csdn.net/cs_lwb https://blog.csdn.net/cs_lwb/article/details/82016997

Android Rxjava+Retrofit封装

一、简介

二、封装步骤

(1)在build文件中加入相关依赖

(2)请求接口服务类

(3)返回结果bean类与统一响应封装

(4)Retrofit封装

(5)Log拦截器代码

(6)Observer基础封装

(7)Observer加入加载框

(8)调度类封装

(9)项目请求再次封装 归纳类

扫描二维码关注公众号,回复: 3300302 查看本文章

三、基本使用

(1)Get请求

(2)Post请求

参考文献:

https://www.jianshu.com/p/ff619fea7e22 

https://blog.csdn.net/impure/article/details/79658098 文件下载

源码地址:

https://gitee.com/blcs/LwbUtils


一、简介

Rxjava与RxAndroid就不在这里介绍,为了更方便,使用较少的代码来实现网络请求。这里对目前比较流行的Retrofit网络框架进行封装。

二、封装步骤

(1)在build文件中加入相关依赖

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    compile 'io.reactivex.rxjava2:rxjava:2.0.1'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.1.0'

(2)请求接口服务类

import java.util.List;
import java.util.Map;
import demo.lwb.com.myutils.bean.Demo;
import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.HeaderMap;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Streaming;
import retrofit2.http.Url;

/**
 * retrofit2 Api接口 Demo
 */
public interface ApiService {

        /**
         * TODO Get请求
         */
        //第一种方式:GET不带参数
        @GET("demo1.txt")
        Observable<Response<BaseResponse<Demo>>> getUser();//中间的BaseResponse 是自己根据后台数据封装的规范 可以进行修改
        @GET
        Observable<Response<Demo>> getUser(@Url String url); //正常情况   添加ResPonse可以根据Response.Code来判断错误类型
        @GET
        Observable<Demo> getUser1(@Url String url); //简洁方式   直接获取所需数据
        //第二种方式:GET带参数
        @GET("api/data/{type}/{count}/{page}")
        Observable<Response<Demo>> getUser(@Path("type") String type, @Path("count") int count, @Path("page") int page);
        //第三种方式:GET带请求参数:https://api.github.com/users/whatever?client_id=xxxx&client_secret=yyyy
        @GET("users/whatever")
        Observable<Response<Demo>> getUser(@Query("client_id") String id, @Query("client_secret") String secret);
        @GET("users/whatever")
        Observable<Response<Demo>> getUser(@QueryMap Map<String, String> info);

        /**
         * TODO POST请求
         */
        //第一种方式:@Body
        @Headers("Accept:application/json")
        @POST("login")
        Observable<Response<Demo>> postUser(@Body RequestBody body);
        //第二种方式:@Field

        @Headers("Accept:application/json")
        @POST("auth/login")
        @FormUrlEncoded
        Observable<retrofit2.Response<Demo>> postUser(@Field("username") String username, @Field("password") String password);
        //多个参数
        Observable<Response<Demo>> postUser(@FieldMap Map<String, String> map);



        /**
         * TODO DELETE
         */
        @DELETE("member_follow_member/{id}")
        Observable<Response<Demo>> delete(@Header("Authorization") String auth, @Path("id") int id);


        /**
         * TODO PUT
         */
        @PUT("member")
        Observable<Response<Demo>> put(@HeaderMap Map<String, String> headers,
                                         @Query("nickname") String nickname);


        /**
         * TODO 文件上传
         */
        @Multipart
        @POST("upload")
        Observable<ResponseBody> upload(@Part("description") RequestBody description,@Part MultipartBody.Part file);

        //亲测可用
        @Multipart
        @POST("member/avatar")
        Observable<Response<Demo>> uploadImage(@HeaderMap Map<String, String> headers, @Part MultipartBody.Part file);



        /**
         * 多文件上传
         * @param params
         * @param description
         * @return
         */
        @Multipart
        @POST("register")
        Observable<ResponseBody> upload(@PartMap Map<String, RequestBody> params, @Part("description") RequestBody description);
        //Observable<ResponseBody> upload(@Part() List<MultipartBody.Part> parts);

        
        @Multipart
        @POST("member/avatar")
        Observable<Response<Demo>> uploadImage1(@HeaderMap Map<String, String> headers, @Part List<MultipartBody.Part> file);


        /**
         * 来自https://blog.csdn.net/impure/article/details/79658098
         * @Streaming 这个注解必须添加,否则文件全部写入内存,文件过大会造成内存溢出
         */
        @Streaming
        @GET
        Observable<ResponseBody> download(@Header("RANGE") String start, @Url String url);

}

(3)返回结果bean类与统一响应封装

public class Demo {
        private String id;
        private String appid;
        private String name;
        private String showtype;
        private String showurl;

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getAppid() {
            return appid;
        }

        public void setAppid(String appid) {
            this.appid = appid;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getShowtype() {
            return showtype;
        }

        public void setShowtype(String showtype) {
            this.showtype = showtype;
        }

        public String getShowurl() {
            return showurl;
        }

        public void setShowurl(String showurl) {
            this.showurl = showurl;
        }
}
/**
 * 统一响应
 * @param <T>
 */
public class BaseResponse<T> {

    private int res_code;
    private int err_code;
    private String err_msg;
    private T Demo;

    public int getRes_code() {
        return res_code;
    }

    public void setRes_code(int res_code) {
        this.res_code = res_code;
    }

    public int getErr_code() {
        return err_code;
    }

    public void setErr_code(int err_code) {
        this.err_code = err_code;
    }

    public String getErr_msg() {
        return err_msg;
    }

    public void setErr_msg(String err_msg) {
        this.err_msg = err_msg;
    }

    public T getDemo() {
        return Demo;
    }

    public void setDemo(T Demo) {
        this.Demo = Demo;
    }
}

(4)Retrofit封装


import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
/**
 * Retrofit封装
 */
public class RetrofitUtils {
    public final static String BaseUrl= "http://oavnqjdk1.bkt.clouddn.com/";
    private static final int DEFAULT_TIME=10;
    private static RetrofitUtils mInstance;
    /**
     * 单例模式
     */
    public static RetrofitUtils getInstance() {
        if (mInstance == null) {
            synchronized (RetrofitUtils.class) {
                if (mInstance == null) {
                    mInstance = new RetrofitUtils();
                }
            }
        }
        return mInstance;
    }

    /**
     * 初始化必要对象和参数
     * @param url  基础baseUrl
     * @return
     */
    public Retrofit getRetrofit(String url) {
        // 初始化okhttp
        OkHttpClient client = new OkHttpClient().newBuilder()
                .readTimeout(DEFAULT_TIME, TimeUnit.SECONDS)//设置读取超时时间
                .connectTimeout(DEFAULT_TIME, TimeUnit.SECONDS)//设置请求超时时间
                .writeTimeout(DEFAULT_TIME,TimeUnit.SECONDS)//设置写入超时时间
                .addInterceptor(new LogInterceptor())//添加打印拦截器
                .retryOnConnectionFailure(true)//设置出现错误进行重新连接。
                .build();
        // 初始化Retrofit
       return  new Retrofit.Builder()
                .client(client)
                .baseUrl(url)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

    //返回一个泛型类
    public static  <T>T getService(Class<T> service){
        return getInstance().getRetrofit(BaseUrl).create(service);
    }

    public static ApiService  getApiService(){
        return getInstance().getRetrofit(BaseUrl).create(ApiService.class);
    }
}

(5)Log拦截器代码

import android.util.Log;
import java.io.IOException;
import java.util.Locale;
import okhttp3.Interceptor;
import okhttp3.Request;

/**
 * Log拦截器代码
 */
public class LogInterceptor implements Interceptor{
    private String TAG = "okhttp";

    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Log.w(TAG,"request:" + request.toString());
        long t1 = System.nanoTime();
        okhttp3.Response response = chain.proceed(chain.request());
        long t2 = System.nanoTime();
        Log.w(TAG,String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",
                response.request().url(), (t2 - t1) / 1e6d, response.headers()));
        okhttp3.MediaType mediaType = response.body().contentType();
        String content = response.body().string();
        Log.w(TAG, "response body:" + content);
        return response.newBuilder()
                .body(okhttp3.ResponseBody.create(mediaType, content))
                .build();
    }
}

(6)Observer基础封装

import android.util.Log;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import retrofit2.Response;

/**
 * 数据返回统一处理  参考https://www.jianshu.com/p/ff619fea7e22
 * @param <T>
 */
public abstract class BaseObserver<T> implements Observer<Response<BaseResponse<T>>> {
    private static final String TAG = "BaseObserver";
    @Override
    public void onNext(Response<BaseResponse<T>> tResponse) {
        Log.e(TAG,"code:==="+tResponse.code());
        Log.e(TAG,"errorBody===:"+tResponse.errorBody());
        Log.e(TAG,"Body===:"+tResponse.body());
        BaseResponse<T> body = tResponse.body();
        if(body.getRes_code()==1){
            onSuccess(body.getDemo());
        }else{
            onFailure(new Exception(body.getErr_msg()), body.getErr_msg());
        }
    }

    @Override
    public void onError(Throwable e) {
        onFailure(e,RxExceptionUtil.exceptionHandler(e));
    }

    @Override
    public void onComplete() {

    }

    @Override
    public void onSubscribe(Disposable d) {

    }

    public abstract void onSuccess(T result);

    public abstract void onFailure(Throwable e,String errorMsg);

}
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import org.json.JSONException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.text.ParseException;
/**
 * 异常处理
 */
public class RxExceptionUtil {
    public static String exceptionHandler(Throwable e){
        String errorMsg = "未知错误";
        if (e instanceof UnknownHostException) {
            errorMsg = "网络不可用";
        } else if (e instanceof SocketTimeoutException) {
            errorMsg = "请求网络超时";
        } else if (e instanceof HttpException) {
            HttpException httpException = (HttpException) e;
            errorMsg = convertStatusCode(httpException);
        } else if (e instanceof ParseException || e instanceof JSONException
                || e instanceof JSONException) {
            errorMsg = "数据解析错误";
        }
        return errorMsg;
    }

    private static String convertStatusCode(HttpException httpException) {
        String msg;
        if (httpException.code() >= 500 && httpException.code() < 600) {
            msg = "服务器处理请求出错";
        } else if (httpException.code() >= 400 && httpException.code() < 500) {
            msg = "服务器无法处理请求";
        } else if (httpException.code() >= 300 && httpException.code() < 400) {
            msg = "请求被重定向到其他页面";
        } else {
            msg = httpException.message();
        }
        return msg;
    }
}

(7)Observer加入加载框


/**
 * Observer加入加载框
 * @param <T>
 */
public abstract class MyObserver<T> extends BaseObserver<T> {
    private boolean mShowDialog;
    private ProgressDialog dialog;
    private Context mContext;
    private Disposable d;

    public MyObserver(Context context, Boolean showDialog) {
        mContext = context;
        mShowDialog = showDialog;
    }

    public MyObserver(Context context) {
        this(context,true);
    }

    @Override
    public void onSubscribe(Disposable d) {
        this.d = d;
        if (!isConnected(mContext)) {
            if (d.isDisposed()) {
                d.dispose();
            }
        } else {
            if (dialog == null && mShowDialog == true) {
                dialog = new ProgressDialog(mContext);
                dialog.setMessage("正在加载中");
                dialog.show();
            }
        }
    }
    @Override
    public void onError(Throwable e) {
        if (d.isDisposed()) {
            d.dispose();
        }
        hidDialog();
        super.onError(e);
    }

    @Override
    public void onComplete() {
        if (d.isDisposed()) {
            d.dispose();
        }
        hidDialog();
        super.onComplete();
    }


    public void hidDialog() {
        if (dialog != null && mShowDialog == true)
            dialog.dismiss();
        dialog = null;
    }
    /**
     * 是否有网络连接,不管是wifi还是数据流量
     *
     * @param context
     * @return
     */
    public static boolean isConnected(Context context)
    {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info == null)
        {
            return false;
        }
        boolean available = info.isAvailable();
        return available;
    }
}

(8)调度类封装


import android.content.Context;
import com.trello.rxlifecycle2.android.ActivityEvent;
import com.trello.rxlifecycle2.components.RxActivity;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
import com.trello.rxlifecycle2.components.support.RxFragment;
import com.trello.rxlifecycle2.components.support.RxFragmentActivity;
import io.reactivex.FlowableTransformer;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

/**
 * 调度类
 */
public class RxHelper {

    public static <T> ObservableTransformer<T, T> observableIO2Main(final Context context) {
        return upstream -> {
            Observable<T> observable = upstream.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
            return composeContext(context, observable);
        };
    }

    public static <T> ObservableTransformer<T, T> observableIO2Main(final RxFragment fragment) {
        return upstream -> upstream.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()).compose(fragment.<T>bindToLifecycle());
    }

    public static <T> FlowableTransformer<T, T> flowableIO2Main() {
        return upstream -> upstream
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    private static <T> ObservableSource<T> composeContext(Context context, Observable<T> observable) {
        if(context instanceof RxActivity) {
            return observable.compose(((RxActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
        } else if(context instanceof RxFragmentActivity){
            return observable.compose(((RxFragmentActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
        }else if(context instanceof RxAppCompatActivity){
            return observable.compose(((RxAppCompatActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
        }else {
            return observable;
        }
    }
}

(9)项目请求再次封装 归纳类

import com.trello.rxlifecycle2.components.support.RxFragment;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.reactivex.Observer;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Response;

/**
 * 项目请求再次封装 归纳类
 */
public class RequestUtils {

    /**
     * Get 请求demo
     * @param context
     * @param observer
     */
    public static void getDemo(RxFragment context,MyObserver<Demo> observer){
        RetrofitUtils.getApiService()
                .getUser().compose(RxHelper.observableIO2Main(context))
                .subscribe(observer);
    }
    /**
     * Post 请求demo
     * @param context
     * @param consumer
     */
    public static void postDemo(RxFragment context, String name, String password, Observer<Response<Demo>> consumer){
        RetrofitUtils.getApiService()
                .postUser(name,password).compose(RxHelper.observableIO2Main(context))
                .subscribe(consumer);
    }
    /**
     * Put 请求demo
     * @param context
     * @param consumer
     */
    public static void putDemo(RxFragment context, String access_token,Observer<Response<Demo>> consumer){
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Accept","application/json");
        headers.put("Authorization",access_token);
        RetrofitUtils.getApiService()
                .put(headers,"",1,"18","123","厦门").compose(RxHelper.observableIO2Main(context))
                .subscribe(consumer);
    }
    /**
     * Delete 请求demo
     * @param context
     * @param consumer
     */
    public static void deleteDemo(RxFragment context, String access_token,Observer<Response<Demo>> consumer){
        RetrofitUtils.getApiService()
                .delete(access_token,1).compose(RxHelper.observableIO2Main(context))
                .subscribe(consumer);
    }

    /**
     * 上传图片
     * @param context
     * @param observer
     */
    public static void upImagView(RxFragment context, String  access_token,String str, Observer<Response<Demo>>  observer){
        File file = new File(str);
//        File file = new File(imgPath);
        Map<String,String> header = new HashMap<String, String>();
        header.put("Accept","application/json");
        header.put("Authorization",access_token);
//        File file =new File(filePath);
        RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
//        RequestBody requestFile =
//                RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part body =
                MultipartBody.Part.createFormData("file", file.getName(), reqFile);
        RetrofitUtils.getApiService().uploadImage(header,body).compose(RxHelper.observableIO2Main(context))
                .subscribe(observer);
    }

    /**
     * 上传多张图片
     * @param files
     */
    public static void upLoadImg(RxFragment context,String access_token,List<File> files, Observer<Response<Demo>>  observer1){
        Map<String,String> header = new HashMap<String, String>();
        header.put("Accept","application/json");
        header.put("Authorization",access_token);
        MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM);//表单类型
        for (int i = 0; i < files.size(); i++) {
            File file = files.get(i);
            RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/*"), file);
            builder.addFormDataPart("file", file.getName(), photoRequestBody);
        }
        List<MultipartBody.Part> parts = builder.build().parts();
        RetrofitUtils.getApiService().uploadImage1(header,parts).compose(RxHelper.observableIO2Main(context))
                .subscribe(observer1);
    }

}

三、基本使用

(1)Get请求

RequestUtils.getDemo(this, new MyObserver<Demo>(getActivity()) {
            @Override
            public void onSuccess(Demo result) {
                tvGet.setText(result.toString());
            }
            @Override
            public void onFailure(Throwable e, String errorMsg) {
                LogUtils.e(errorMsg);
            }
        });

(2)Post请求

(没有使用MyObserver,需要根据后台返回的数据来封装适合自己的Obsever)

 RequestUtils.postDemo(this, "aaa", "sss", new Observer<Response<Demo>>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Response<Demo> loginBeanResponse) {
                Log.e(TAG, "onNext: "+ loginBeanResponse.code());
                
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

参考文献:

https://www.jianshu.com/p/ff619fea7e22 

https://blog.csdn.net/impure/article/details/79658098​​​​​​​ 文件下载

源码地址:

https://gitee.com/blcs/LwbUtils

猜你喜欢

转载自blog.csdn.net/cs_lwb/article/details/82016997