Retrofit2.0簡單封裝成統(tǒng)一接口處理網(wǎng)絡請求

最新版
我還在擁抱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,不必在意這些細節(jié)
        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 比著源碼來一發(fā)
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("#發(fā)起請求#");
        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); \才會執(zhí)行到這里,
    @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 上修改后的聯(lián)網(wǎng)帶馬
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); // 已經(jīng)解密過了,注釋掉
                        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 回調函數(shù)加上
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下,一些代碼需要注釋掉,提供些思路,僅供參考~~~
紙上得來終覺淺,絕知此事要躬行~ 多動動手寫寫代碼,也是很好的~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末茶行,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子种吸,更是在濱河造成了極大的恐慌肴掷,老刑警劉巖维贺,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沐序,死亡現(xiàn)場離奇詭異秸脱,居然都是意外死亡蛋叼,警方通過查閱死者的電腦和手機焊傅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門剂陡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狐胎,你說我怎么就攤上這事鹏倘。” “怎么了顽爹?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵纤泵,是天一觀的道長。 經(jīng)常有香客問我镜粤,道長捏题,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任肉渴,我火速辦了婚禮公荧,結果婚禮上,老公的妹妹穿的比我還像新娘同规。我一直安慰自己循狰,他們只是感情好,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布券勺。 她就那樣靜靜地躺著绪钥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪关炼。 梳的紋絲不亂的頭發(fā)上儒拂,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天社痛,我揣著相機與錄音,去河邊找鬼斩箫。 笑死校焦,一個胖子當著我的面吹牛,可吹牛的內容都是我干的房匆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼花竞!你這毒婦竟也來了掸哑?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤厌蔽,失蹤者是張志新(化名)和其女友劉穎奴饮,沒想到半個月后择浊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡叉瘩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年薇缅,在試婚紗的時候發(fā)現(xiàn)自己被綠了泳桦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灸撰。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖债蓝,靈堂內的尸體忽然破棺而出盛龄,到底是詐尸還是另有隱情,我是刑警寧澤啊鸭,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布赠制,位于F島的核電站赂摆,受9級特大地震影響,放射性物質發(fā)生泄漏库正。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一褥符、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抚垃,春花似錦、人聲如沸鹤树。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曲伊。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間邑狸,已是汗流浹背赚哗。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工硅堆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留够掠,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓朴乖,卻偏偏與公主長得像祖屏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子买羞,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內容