Retrofit2.0简单封装成统一接口处理网络请求

最新版
我还在拥抱Eclipse,用的都是jar包,用到的jar包我放到云盘

链接:http://pan.baidu.com/s/1gfIf0Gj 密码:y6eh

看完很多Retrofit2.0文章后,我岂不是要这样干,忘了告诉你,我们线上接口不下50个吆~
为什么如下定义呢?我们的接口是https://www.xxx.xxx?data=json(加密的)这样的吆~
1.来个获取banner的

package api;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
import bean.BannerResp;

public interface IBannerService {
    @FormUrlEncoded
    @POST("/")
    public Call<BannerResp> getBanner(@Field("data") String json);
}

2.来个登陆的

package api;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
import bean.BannerResp;

public interface ILoginService {
    @FormUrlEncoded
    @POST("/")
    public Call<LoginResp> getBanner(@Field("data") String json);
}

3.来个注册的

package api;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
import bean.BannerResp;

public interface IRegisterService {
    @FormUrlEncoded
    @POST("/")
    public Call<RegisterResp> getBanner(@Field("data") String json);
}

4.来个评论的

package api;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
import bean.BannerResp;

public interface ICommentService {
    @FormUrlEncoded
    @POST("/")
    public Call<CommentResp> getBanner(@Field("data") String json);
}

等等等等,大兄弟,你这样写累不累!!!

我打算这样干,这事鲨鱼也干了~~嘿嘿

代码如下:

package api;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
import bean.BannerResp;

public interface Api<T> {
    @FormUrlEncoded
    @POST("/")
    public Call<T> doPost(@Field("data") String json);
}

打造通用的接口,拒绝重复代码我认为这样写不错,一劳永逸,并且是自己的风格,绝对不是外面妖艳的货色能比的吆~
光写不行啊,跑起来看看哥哎,我正有此意,别急赛
国际惯例,别人家都这样写,我就不和别人不一样,是的,你没看错,和别人写的一样一样的....
构造Retrofit2君

package http;

import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import api.IBannerService;
import bean.BannerResp;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.wyhd.encry.decry.security.util.AesEncryptionUtil;

import factory.HttpLoggingInterceptor;
import factory.IGsonFactory;

public class RetrofitHelper {
    /** 基本路径 */
    public static final String BASE_URL = "https://api.imeizan.cn";

    public static void tst(String json) {
        json = AesEncryptionUtil.encrypt(json); // 加密json,不必在意这些细节
        Gson gson = new GsonBuilder().setLenient().create();
        Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                .client(getOkHttpClient())
                .addConverterFactory(IGsonFactory.create(gson)).build();
        Api service = retrofit.create(Api.class);
        Call<BannerResp> call = service.doPost(json);
        call.enqueue(new Callback<BannerResp>() {

            @Override
            public void onResponse(Call<BannerResp> call,
                    Response<BannerResp> resp) {
                BannerResp body = resp.body();
                System.out.println("异步返回:" + body.toString());
            }

            @Override
            public void onFailure(Call<BannerResp> msg, Throwable error) {
                System.out.println(msg.toString() + "|" + error.getMessage());
            }
        });
        final Call<BannerResp> clone = call.clone();
        new Thread() {
            public void run() {
                try {
                    Response<BannerResp> execute = clone.execute();
                    System.out.println("同步返回:" + execute.body().toString());
                } catch (Exception e) {
                    System.out.println("同步返回:" + e.getMessage());
                }
            };
        }.start();

    }

      public static OkHttpClient getOkHttpClient() {
        // 日志显示级别
        HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;
        // 新建log拦截器
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(
                new HttpLoggingInterceptor.Logger() {
                    @Override
                    public void log(String message) {
                        System.out.println(message);
                    }
                });
        loggingInterceptor.setLevel(level);
        // 定制OkHttp
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        // OkHttp进行添加拦截器loggingInterceptor
        httpClientBuilder.addInterceptor(loggingInterceptor);
        return httpClientBuilder.build();
    }
}

然后呢?妈的..当然是跑起来啊~
等等,先奉上请求,响应体,为什么那么写?接口那样的定义,我也很无奈啊~

  • 1.banner请求体
package bean;

import java.io.Serializable;

public class BannerReq implements Serializable {
    private static final long serialVersionUID = 1L;
    public int num;
    public String version="v1.0.0";
    public String system = "360";
    public BannerReq(int num) {
        super();
        this.num = num;
    }


    @Override
    public String toString() {
        return "BannerReq [num=" + num + ", version=" + version + ", system="
                + system + "]";
    }

}
  • 2.banner响应体
package bean;

import java.io.Serializable;
import java.util.List;

public class BannerResp implements Serializable {
    private static final long serialVersionUID = 1L;
    public int code;
    public int num;
    public String msg;
    public List<Banner> data;

    public class Banner implements Serializable {
        private static final long serialVersionUID = 1L;
        public String id;
        public String name;

        @Override
        public String toString() {
            return "Banner [id=" + id + ", name=" + name + "]";
        }

    }

    @Override
    public String toString() {
        return "BannerResp [code=" + code + ", num=" + num + ", msg=" + msg
                + ", data=" + data + "]";
    }

}

别他妈催了,这就跑了吆,万事俱备只欠东风,bingo...

package com.july.testunit;

import http.RetrofitHelper;
import android.app.Activity;
import android.os.Bundle;
import bean.BannerReq;

import com.google.gson.Gson;
import com.july.retrfit.R;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        BannerReq req = new BannerReq(1); // 接口号1是banner
        Gson gson = new Gson();
        String json = gson.toJson(req);
        RetrofitHelper.tst(json);
    }
}

运行结果如下:

Are you kidding me!!!

package api;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface Api<T> {
    public final String KEY = "data";

    @FormUrlEncoded
    @POST("/")
    public Call<T> doPost(@Field(KEY) String json);
}

这样写,不存在的...
改吧改吧

package api;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface Api {
    public final String KEY = "data";

    @FormUrlEncoded
    @POST("/")
    public Call<String> doPost(@Field(KEY) String json);
}

报告老板,我觉得写成通用的应该是这样~~

好了,废话太多,来不及了,赶紧上车!!!

返回String吆,需要自定义GsoncovertFactory

别害怕,GsoncovertFactory人很好,说话又好听

  • 1 比着源码来一发
package factory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;

public class IGsonFactory2 extends Converter.Factory {
    public static IGsonFactory2 create() {
        return create(new GsonBuilder().setLenient().create());
    }

    public static IGsonFactory2 create(Gson gson) {
        if (gson == null)
            throw new NullPointerException("gson == null");
        return new IGsonFactory2(gson);
    }

    private final Gson gson;

    private IGsonFactory2(Gson gson) {
        this.gson = gson;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type,
            Annotation[] annotations, Retrofit retrofit) {
        return new IResponseBodyConverter2(); // 响应
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
            Annotation[] parameterAnnotations, Annotation[] methodAnnotations,
            Retrofit retrofit) {
        System.out.println("#发起请求#");
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new IRequestBodyConverter2<>(gson, adapter); // 请求
    }
}

  • 2 requestbody,基本不动
package factory;

import java.io.IOException;
import java.nio.charset.Charset;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import retrofit2.Converter;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.wyhd.encry.decry.security.util.AesEncryptionUtil;

/**
 * RequestBody 对请求体进行加密处理
 */
public class IRequestBodyConverter2<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType
            .parse("application/json; charset=UTF-8");
    static final Charset UTF_8 = Charset.forName("UTF-8");

    final Gson gson;
    final TypeAdapter<T> adapter;

    IRequestBodyConverter2(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
        System.out.println("#IRequestBodyConverter初始化#");
    }
        // 接口如果这样定义 void doPost(@Body by); \才会执行到这里,
    @Override
    public RequestBody convert(T value) throws IOException {
        String json = value.toString();
        System.out.println("#加密前#" + json);
        json = AesEncryptionUtil.encrypt(json);
        System.out.println("#加密后#" + json);
        return RequestBody.create(MEDIA_TYPE, json);
    }
}

  • 3 核心代码了
package factory;

import java.io.IOException;

import okhttp3.ResponseBody;
import retrofit2.Converter;

import com.wyhd.encry.decry.security.util.AesEncryptionUtil;

public class IResponseBodyConverter2 implements Converter<ResponseBody, String> {

    @Override
    public String convert(ResponseBody value) throws IOException {
        String string = value.string();
        System.out.println("#解密前@#" + string);
        string = AesEncryptionUtil.decrypt(string);
        System.out.println("#解密后@#" + string);
        return string;
    }
}
  • 4 上修改后的联网带马
public class HttpRequestFactory {
    public static final Gson GSON = new Gson();
    public static final String TAG = HttpRequestFactory.class.getSimpleName();
    public static final String BASE_URL = "https://api.imeizan.cn";
    public static String reqParams(Object src) {
        String json = "";
        if (src != null && src instanceof String) {
            json = (String) src;
        } else {
            if (src == null) {
            } else {
                json = GSON.toJson(src);
            }
        }
        return json;
    }

    public static <T> void exec3(Object src, final ResultCallback<T> mCallback) {
        String json = reqParams(src);
        json = AesEncryptionUtil.encrypt(json);
        Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                .client(getOkHttpClient())
                .addConverterFactory(IGsonFactory.create(GSON)).build();
        Api api = retrofit.create(Api.class);
        Call<String> doPost = api.doPost(json);
        doPost.enqueue(new Callback<String>() {

            @Override
            public void onFailure(Call<String> request, Throwable error) {
                System.out.println("#失败回调#");
                if (mCallback != null) {
                    mCallback.onError(null, error);
                }
            }

            @Override
            public void onResponse(Call<String> call, Response<String> resp) {
                System.out.println("#成功回调#");
                if (mCallback != null) {
                    if (resp.isSuccessful()) {
                        String finalStr = "";
                        String string = resp.body();
                        // finalStr = AesEncryptionUtil.decrypt(string); // 已经解密过了,注释掉
                        finalStr = string;
                        if (mCallback.mType != null) {
                            if (mCallback.mType == String.class) {
                                if (Tools.isEmpty(finalStr)) {
                                    Exception e = new Exception(
                                            "AesEncryptionUtil.decrypt(string) return null!");
                                    exeFailedCallback(call, e, mCallback);
                                } else {
                                    exeSuccessCallback(finalStr, mCallback);
                                }
                            } else {
                                Object o = GSON.fromJson(finalStr,
                                        mCallback.mType);
                                if (o == null) {
                                    Exception e = new Exception(
                                            "mGson.fromJson(finalStr,callback.mType) return null!");
                                    exeFailedCallback(call, e, mCallback);
                                } else {
                                    exeSuccessCallback(o, mCallback);
                                }
                            }
                        } else {
                            Throwable e = new Throwable("mCallback.mType 为空!!!");
                            exeFailedCallback(call, e, mCallback);
                        }
                    } else {
                        Throwable e = new Throwable(resp.toString());
                        exeFailedCallback(call, e, mCallback);
                    }
                }
            }
        });
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void exeFailedCallback(final Call call, final Throwable e,
            final ResultCallback<?> callback) {
        if (callback != null) {
            callback.onError(call, e);
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void exeSuccessCallback(Object o, final ResultCallback callback) {
        if (callback != null) {
            callback.onResponse(o);
        }
    }

    public static OkHttpClient getOkHttpClient() {
        // 日志显示级别
        HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;
        // 新建log拦截器
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(
                new HttpLoggingInterceptor.Logger() {
                    @Override
                    public void log(String message) {
                        System.out.println(message);
                    }
                });
        loggingInterceptor.setLevel(level);
        // 定制OkHttp
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        // OkHttp进行添加拦截器loggingInterceptor
        httpClientBuilder.addInterceptor(loggingInterceptor);
        return httpClientBuilder.build();
    }
}
  • 5 回调函数加上
package callback;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import com.google.gson.internal.$Gson$Types;

import retrofit2.Call;

public abstract class ResultCallback<T> {
    public Type mType;

    public ResultCallback() {
        mType = getSuperclassTypeParameter(getClass());
    }

    static Type getSuperclassTypeParameter(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return $Gson$Types
                .canonicalize(parameterized.getActualTypeArguments()[0]);
    }

    public abstract void onError(Call<T> request, Throwable e);

    public abstract void onResponse(T response);
}

  • 6 测试
package com.july.retrfit;

import http.HttpRequestFactory;
import http.RetrofitHelper002;
import retrofit2.Call;
import android.app.Activity;
import android.os.Bundle;
import bean.BannerReq;
import bean.BannerResp;
import callback.ResultCallback;

import com.google.gson.Gson;
import com.july.retrfit.R;
import com.wyhd.common.sdk.Logger;

public class MainActivity extends Activity {
    private String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取banner 接口号1
        BannerReq req = new BannerReq(1);
        HttpRequestFactory.exec3(req, new ResultCallback<BannerResp>() {

            @Override
            public void onError(Call<BannerResp> request, Throwable e) {
                Logger.log(TAG, "##失败##" + e.getMessage());
            }

            @Override
            public void onResponse(BannerResp response) {
                Logger.log(TAG, "##成功##" + response);
            }
        });
        
        //登陆接口 接口号3
        LoginReq req2 = new LoginReq(3,"账号","密码");
        HttpRequestFactory.exec3(req2, new ResultCallback<LoginResp>() {

            @Override
            public void onError(Call<LoginResp> request, Throwable e) {
                Logger.log(TAG, "##失败##" + e.getMessage());
            }

            @Override
            public void onResponse(LoginResp response) {
                Logger.log(TAG, "##成功##" + response);
            }
        });
        
    }
}

到此为止,Retrofit2通用接口编写完毕,运行结果???
这个,不看不行吗?
美图你说个杰宝,也是哈~
测试成功,不要较真


忘了说了,我还在拥抱Eclipse,你们会不会打死我....

retrofit 封装之路(一)
链接:http://pan.baidu.com/s/1qXPErAO 密码:hgqf
retrofit 封装之路(二)
链接:http://pan.baidu.com/s/1bo5Mf1P 密码:andk
retrofit 封装之路(三) |retrofit + rxjava系
链接:http://pan.baidu.com/s/1o7RKoZo 密码:zuaw

代码量不多,jar包放在assert下,一些代码需要注释掉,提供些思路,仅供参考~~~
纸上得来终觉浅,绝知此事要躬行~ 多动动手写写代码,也是很好的~

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

推荐阅读更多精彩内容