封装自己Retrofit2+rxjava请求客户端

前言

目前Android 请求框架层出不穷,主流的框架有一下几种,

Android-Async-Http、

Volley、

OkHttp、

Retrofit

而Retrofit备受大家的喜爱,当然也是因为它确实好用。

本文就针对Retrofit进行简单的封装,主要对自己近一年对该框架的使用情况进行整理。这里不再讲解原生retrofit的使用。

正式开始

客户端的封装:

/**
 * @author KangLong
 * date 2017/5/8
 * description 快速 构建Retrofit请求类
 */
public class MyRetrofitClient {

    public static String baseUrl = BaseApiService.BASE_URL_DAFULT;
    private static final long TIMEOUT = 10;
    private static final String TAG = "MyRetrofitClient";
    private Retrofit retrofit;
    private static Context mContext;
    private OkHttpClient mOkHttpClient;

    public final static Map<String, String> baseUrlMap = new HashMap<>();

    static {
        baseUrlMap.put("zhihu", BaseApiService.BASE_URL_ZHIHU);
        baseUrlMap.put("baidu", BaseApiService.BASE_URL_BAIDU);
    }

    public static MyRetrofitClient getInstance(Context context) {
        if (context != null) {
            mContext = context;
        }
        return SingletonHolder.INSTANCE;
    }

    private static MyRetrofitClient getInstance(Context context, String url) {
        if (context != null) {
            mContext = context;
        }
        return new MyRetrofitClient(context, url);
    }

    /**
     * 用于自定义url的请求和添加token的请求
     *
     * @param context 上下文
     * @param url     自定义baseUrl
     * @param headers 自定义添加的header
     * @return
     */
    private static MyRetrofitClient getInstance(Context context, String url, Map<String, String> headers) {
        if (context != null) {
            mContext = context;
        }
        return new MyRetrofitClient(context, url, headers);
    }

    /**
     * 创建内部类单利
     */
    private static class SingletonHolder {
        private static MyRetrofitClient INSTANCE = new MyRetrofitClient(mContext);
    }

    private MyRetrofitClient() {
    }

    /**
     * 构造函数,用于初试化
     *
     * @param context
     */
    private MyRetrofitClient(Context context) {
        this(context, null);
    }

    private MyRetrofitClient(Context context, String url) {
        this(context, url, null);
    }

    private MyRetrofitClient(Context context, String url, Map<String, String> headers) {
        if (TextUtils.isEmpty(url)) {
            url = baseUrl;
        }
        File mFile = new File(context.getCacheDir() + "http");//储存目录
        long maxSize = 10 * 1024 * 1024; // 10 MB 最大缓存数
        Cache mCache = new Cache(mFile, maxSize);
        mOkHttpClient = new OkHttpClient.Builder()
                //添加Cookie管理,不需要管理可以不加,token在Cookie中的时候需要添加
                .cookieJar(new CookieManger(context.getApplicationContext()))
                //添加统一的请求头
                .addInterceptor(new BaseInterceptor(headers))
                //添加base改变拦截器
                .addInterceptor(new BaseUrlInterceptor())
                //添加缓存拦截器
                .addNetworkInterceptor(new CaheInterceptor(context))
                //打印请求信息(可以自定义打印的级别!!)
                .addNetworkInterceptor(new HttpLoggingInterceptor(/*message -> Log.e(TAG, message)*/).setLevel(HttpLoggingInterceptor.Level.BODY))
                //相关请求时间设置
                .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
                //添加缓存
                .cache(mCache)
                .connectionPool(new ConnectionPool(8, 15, TimeUnit.SECONDS))
                // 这里你可以根据自己的机型设置同时连接的个数和时间,我这里8个,和每个保持时间为15s
                .build();

        retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .client(mOkHttpClient)
                //添加转换器String
                .addConverterFactory(ScalarsConverterFactory.create())
                //这里是转换器  这里采用Gson做转换器
                .addConverterFactory(GsonConverterFactory.create())
                //添加RXjava做适配器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    /**
     * 用于构建请求代理,BaseApiService中没有包含时可以用这个
     *
     * @param service
     * @param <T>
     * @return
     */
    public <T> T createService(Class<T> service) {
        if (service == null) {
            throw new RuntimeException("Api service is null!");
        }
        return retrofit.create(service);
    }

    /**
     * 通过代理构建接口
     *
     * @return
     */
    public BaseApiService createService() {
        return retrofit.create(BaseApiService.class);
    }
}
image.gif

简单使用:没有参数

在baseApiService中配置

    /**
     * (示例无参数请求)
     * 这里用默认回调
     * 获取版本号
     *
     * @param
     * @return
     */
    @Headers({URL_NAME + BASE_URL_ZHIHU})
    @GET("/api/4/version/android/2.3.0")
    Call<BaseResponse<Resond>> getVersionDefult();
image.gif

使用客户端调用

 MyRetrofitClient.getInstance(this)
                .createService()
                .getVersionDefult()
                .enqueue(new Callback<BaseResponse<Resond>>() {
                    @Override
                    public void onResponse(Call<BaseResponse<Resond>> call, Response<BaseResponse<Resond>> response) {
                        textView.setText(response.body().toString());
                    }

                    @Override
                    public void onFailure(Call<BaseResponse<Resond>> call, Throwable t) {

                    }
                });

[图片上传中...(image-935289-1538296683823-6)]

带参数,配合Rxjava

在baseApiService中配置

    /**
     * 只有一个参数
     *
     * @param mobile 手机号
     * @return
     */
    @GET("/fitness/coach/login/code.jhtml")
    Observable<BaseResponse<String>> getVerificatCode(@Query("mobile") String mobile);

[图片上传中...(image-103b43-1538296683823-5)]

调用方式

MyRetrofitClient.getInstance(this)
                .createService()
                .getVerificatCode("18380426497")
                .compose(RxHelper.io_main(this))
                .subscribe(new BaseObserver<String>(this) {

                    @Override
                    protected void onSuccess(String value) {
                        textView.setText(value.toString());
                    }

                    @Override
                    protected void onBefore(Disposable d) {

                    }

                    @Override
                    protected void onFailure(String message) {

                    }
                });

[图片上传中...(image-9e2353-1538296683823-4)]

上传图片

在baseApiService中配置

    /**
     * 上传资源的封面
     *
     * @param body 文件
     * @return
     */
    @POST("/fitness/coach/member/uploadCover.jhtml")
    Observable<BaseResponse<String>> uploadCover(@Body RequestBody body);

[图片上传中...(image-9b3cb9-1538296683823-3)]

调用方式

 File file = new File("/你的文件路径");
        RequestBody mBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("file", "cover.jpg", RequestBody.create(MediaType.parse("image/*"), file))
                .build();
        MyRetrofitClient.getInstance(this)
                .createService()
                .uploadCover(mBody)
                .compose(RxHelper.io_main(this))
                .subscribe(new BaseObserver<String>(this) {
                    @Override
                    protected void onSuccess(String value) {
                        textView.setText(value.toString());

                    }

                    @Override
                    protected void onBefore(Disposable d) {

                    }

                    @Override
                    protected void onFailure(String message) {

                    }
                });

[图片上传中...(image-99c2c7-1538296683823-2)]

上传多张图片/视频/或者图文同时传

在baseApiService中配置

  /**
     * @param body
     * @return //难度星级
     * private int star
     * <p>
     * //时长
     * private Integer duration
     * <p>
     * private TrainType trainType
     * //封面
     * private String cover
     * //标题
     * private String title
     * private String content
     * private String file;
     * public enum TrainType
     * {
     * //5分钟器械
     * FIVE_MINI_INSTREMENT,
     * //5分钟徒手
     * FIVE_MINI_UNARMED,
     * //5分钟柔韧
     * FIVE_MINI_PLIABLE,
     * }
     */

    @POST("/fitness/coach/member/uploadVideo.jhtml")
    Observable<BaseResponse<String>> uploadCourse(@Body RequestBody body);

[图片上传中...(image-5294a5-1538296683823-1)]

调用方式

 File file1 = new File("/你的文件路径");
        File file2 = new File("/你的文件路径");
        File file3 = new File("/你的文件路径");
        File file4 = new File("/你的文件路径");
        File file5 = new File("/你的文件路径");
        RequestBody mBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("file1", file1.getName(), RequestBody.create(MediaType.parse("video/*"), file1))
                .addFormDataPart("file2", file2.getName(), RequestBody.create(MediaType.parse("video/*"), file2))
                .addFormDataPart("file3", file3.getName(), RequestBody.create(MediaType.parse("video/*"), file3))
                .addFormDataPart("file4", file4.getName(), RequestBody.create(MediaType.parse("video/*"), file4))
                .addFormDataPart("file5", file5.getName(), RequestBody.create(MediaType.parse("video/*"), file5))
                .addFormDataPart("duration", 10 + "")
                .addFormDataPart("star", String.valueOf(5))
                .addFormDataPart("trainType", "trainType")
                .addFormDataPart("content", "content")
                .addFormDataPart("cover", "cover")
                .addFormDataPart("title", "title")
                .build();
        MyRetrofitClient.getInstance(this)
                .createService()
                .uploadCourse(mBody)
                .compose(RxHelper.io_main(this))
                .subscribe(new BaseObserver<String>(this) {
                    @Override
                    protected void onSuccess(String value) {
                        textView.setText(value.toString());
                    }

                    @Override
                    protected void onBefore(Disposable d) {

                    }

                    @Override
                    protected void onFailure(String message) {

                    }
                });

[图片上传中...(image-a19128-1538296683821-0)]

总结

封装中还包含了动态改变BaseUrl动态添加header中断请求等等常用功能。后会添加MVP+Dagger2的方式封装。

关于特别的方式,及文件详情见demo,有问题欢迎issue,喜欢请star支持一下哟!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容