前言:
網絡請求是絕大多數app中比不可少的工具,對于我而言,從最初的xutils,到vollay,再到okhttp,最後到了今天的retrofit,相對而言,每個都有每個的優點,并不能完全說誰好誰壞,其實我覺得用你最熟悉的,你覺得最好的,最友善的,他就是最好的,到目前為止,我相信還是有一些公司的項目在用xutils,或者vollay的,如果說盲目的追求新東西,而最後出現一堆bug,這恐怕是所有程式猿最不想看到的結果,隻要你技術過硬,你就能封裝一套最适合你的,好了廢話不多說,下面我就帶領大家來簡單的封裝一套屬于你自己的retrofit網絡請求,讓你的網絡請求更簡單友善,此封裝并沒有包含所有請求方式,這裡隻以get請求為例,其他方式自行開闊,後續會将所有請求方式添加到 YcRetrofitUtils源碼中,
1.添加相關依賴
//檔案内部使用
def butterknifeLatestReleaseVersion = '8.5.1' //butterknife插件的版本
def supportLibraryVersion = '27.1.1'
//外部使用的安卓版本相關
ext {
applicationId = 'com.yc.androidarchitecture'
compileSdkVersion = 27
targetSdkVersion = 27
minSdkVersion = 19
buildToolsVersion = "27.1.1"
versionCode = 0
versionName = "1.0.0"
}
//compile依賴的第三方庫
ext.deps = [
supportv4 : "com.android.support:support-v4:$supportLibraryVersion",
supportv7 : "com.android.support:appcompat-v7:$supportLibraryVersion",
recyclerviewv7 : "com.android.support:recyclerview-v7:$supportLibraryVersion",
constraintlayout : 'com.android.support.constraint:constraint-layout:1.1.2',
//增加butterknife 插件相關的庫 (版本用内部定義的方式,友善管理)
butterknife : "com.jakewharton:butterknife:$butterknifeLatestReleaseVersion",
butterknifeCompiler : "com.jakewharton:butterknife-compiler:$butterknifeLatestReleaseVersion",
YcAndroidUtils : 'com.yc:YcAndroidUtils:1.1.7',
design : "com.android.support:design:$supportLibraryVersion",
//網絡請求依賴庫
rxjava : "io.reactivex.rxjava2:rxjava:2.1.1",
rxandroid : "io.reactivex.rxjava2:rxandroid:2.0.1",
retrofit : "com.squareup.retrofit2:retrofit:2.3.0",
retrofit2_converter_gson : "com.squareup.retrofit2:converter-gson:2.3.0",
retrofit2_adapter_rxjava2 : "com.squareup.retrofit2:adapter-rxjava2:2.3.0",
okhttp3_logging_interceptor: "com.squareup.okhttp3:logging-interceptor:3.10.0",
]
在Application中初始化一下工具類
/**
* 設定baseUrl 及 ApiService (必填項)
* 如果你覺得 BaseApiService預設的不能滿足你的需求 可繼承BaseApiService後傳入你自己定義的BaseApiService
*/
YcRetrofitUtils builder = YcRetrofitUtils.getInstance()
.init(this) //初始化
.setBaseUrl("http://v.juhe.cn/")
// .setReadTimeOut(100)//預設 60000
// .setWriteTimeOut(100)//預設 60000
// .setConnectTimeout(100)//預設 60000
.build()
.create();
basicUseService = builder.create(BasicUseService.class);
2.在base類中建立 BaseApiService,這裡隻實作get方式,其他的方式根據需求自己添加就好
/**
* Created by yc on 2018/4/3.
*/
public interface BaseApiService {
@GET()
Flowable<ResponseBody> get(@Url String url);
@GET()
Flowable<ResponseBody> get(@Url String url, @QueryMap Map<String, String> maps);
@POST()
@FormUrlEncoded
Flowable<ResponseBody> post(@Url String url, @FieldMap Map<String, String> maps);
@POST()
Flowable<ResponseBody> postBody(@Url String url, @Body Object object);
@DELETE()
Flowable<ResponseBody> delete(@Url String url, @QueryMap Map<String, String> maps);
@PUT()
Flowable<ResponseBody> put(@Url String url, @QueryMap Map<String, String> maps);
@POST()
Flowable<ResponseBody> putBody(@Url String url, @Body Object object);
@Multipart
@POST()
Flowable<ResponseBody> uploadFlie(@Url String fileUrl, @Part("description") RequestBody description, @Part("files") MultipartBody.Part file);
@Multipart
@POST()
Flowable<ResponseBody> uploadFiles(@Url String url, @PartMap() Map<String, RequestBody> maps);
@Multipart
@POST()
Flowable<ResponseBody> uploadFiles(@Url String url, @Part() List<MultipartBody.Part> parts);
@Streaming
@GET
Flowable<ResponseBody> downloadFile(@Url String fileUrl);
@POST()
@Headers({"Content-Type: application/json", "Accept: application/json"})
Flowable<ResponseBody> postJson(@Url String url, @Body RequestBody jsonBody);
@POST()
Flowable<ResponseBody> postBody(@Url String url, @Body RequestBody body);
}
3.工具類的封裝在代碼中詳細講解
public class YcRetrofitUtils {
private static Application sContext;
public static final int DEFAULT_MILLISECONDS = 60000; //預設的逾時時間
private static final int DEFAULT_RETRY_COUNT = 3; //預設重試次數
private static final int DEFAULT_RETRY_INCREASEDELAY = 0; //預設重試疊加時間
private static final int DEFAULT_RETRY_DELAY = 500; //預設重試延時
public static final int DEFAULT_CACHE_NEVER_EXPIRE = -1; //緩存過期時間,預設永久緩存
private String mBaseUrl; //全局BaseUrl
private long mConnectTimeout; //連結逾時
private long mReadTimeOut; //讀逾時
private long mWriteTimeOut; //寫逾時
private static int mRetryCount = DEFAULT_RETRY_COUNT; //重試次數預設3次
private static int mRetryDelay = DEFAULT_RETRY_DELAY; //延遲xxms重試
private static int mRetryIncreaseDelay = DEFAULT_RETRY_INCREASEDELAY; //疊加延遲
private OkHttpClient.Builder okHttpClientBuilder; //okhttp請求的用戶端
private Retrofit.Builder retrofitBuilder; //Retrofit請求Builder
private Retrofit retrofit;
private Interceptor mInterceptor; //okhttp的攔截器
private Converter.Factory mConverterFactory; //Retrofit全局設定Converter.Factory
private CallAdapter.Factory mCallAdapterFactory; //Retrofit全局設定CallAdapter.Factory
private static BaseApiService mBaseApiService; //通用的的api接口
//定義公共的參數
private static Map<String, RequestBody> params;
private volatile static YcRetrofitUtils sInstance = null;
private static DisposableSubscriber sDisposableSubscriber;
private YcRetrofitUtils() {
okHttpClientBuilder = new OkHttpClient.Builder();
retrofitBuilder = new Retrofit.Builder();
}
public static YcRetrofitUtils getInstance() {
if (sInstance == null) {
synchronized (YcRetrofitUtils.class) {
if (sInstance == null) {
sInstance = new YcRetrofitUtils();
params = new HashMap<String, RequestBody>();
}
}
}
return sInstance;
}
public static BaseApiService getBaseApiService() {
return mBaseApiService;
}
/**
* 必須在全局Application先調用,擷取context上下文,否則緩存無法使用
*/
public YcRetrofitUtils init(Application app) {
sContext = app;
return this;
}
/**
* 擷取全局上下文
*/
public static Context getContext() {
initialize();
return sContext;
}
private static void initialize() {
if (sContext == null)
throw new ExceptionInInitializerError("請先在全局Application中調用 YcRetrofitinit() 初始化!");
}
//okhttp的執行個體
public static OkHttpClient getOkHttpClient() {
return getOkHttpClientBuilder().build();
}
public static Retrofit getRetrofit() {
return getRetrofitBuilder().build();
}
/**
* 對外暴露 OkHttpClient,友善自定義
*/
public static OkHttpClient.Builder getOkHttpClientBuilder() {
return getInstance().okHttpClientBuilder;
}
/**
* 對外暴露 Retrofit,友善自定義
*/
public static Retrofit.Builder getRetrofitBuilder() {
return getInstance().retrofitBuilder;
}
/**
* 全局為Retrofit設定自定義的OkHttpClient
*/
public YcRetrofitUtils setOkclient(OkHttpClient client) {
getRetrofitBuilder().client(checkNotNull(client, "OkClient == null"));
return this;
}
/**
* 全局設定Interceptor,預設HttpLoggingInterceptor.Level.BODY
*/
public YcRetrofitUtils addOkHttpInterceptor(Interceptor interceptor) {
mInterceptor = checkNotNull(interceptor, "OkHttpAddInterceptor == null");
getOkHttpClientBuilder().addInterceptor(mInterceptor);
return this;
}
/**
* 全局設定Converter.Factory,預設GsonConverterFactory.create()
*/
public YcRetrofitUtils addConverterFactory(Converter.Factory factory) {
mConverterFactory = checkNotNull(factory, "RetrofitConverterFactory == null");
getRetrofitBuilder().addConverterFactory(mConverterFactory);
return this;
}
/**
* 全局設定CallAdapter.Factory,預設RxJavaCallAdapterFactory.create()
*/
public YcRetrofitUtils addCallAdapterFactory(CallAdapter.Factory factory) {
mCallAdapterFactory = checkNotNull(factory, "RetrofitCallAdapterFactory == null");
getRetrofitBuilder().addCallAdapterFactory(mCallAdapterFactory);
return this;
}
/**
* 全局讀取逾時時間
*/
public YcRetrofitUtils setReadTimeOut(long readTimeOut) {
if (readTimeOut < 0)
throw new IllegalArgumentException("retryCount must > 0");
mReadTimeOut = readTimeOut;
getOkHttpClientBuilder().readTimeout(readTimeOut, TimeUnit.MILLISECONDS);
return this;
}
/**
* 全局寫入逾時時間
*/
public YcRetrofitUtils setWriteTimeOut(long writeTimeout) {
if (writeTimeout < 0)
throw new IllegalArgumentException("retryCount must > 0");
mWriteTimeOut = writeTimeout;
getOkHttpClientBuilder().writeTimeout(writeTimeout, TimeUnit.MILLISECONDS);
return this;
}
/**
* 全局連接配接逾時時間
*/
public YcRetrofitUtils setConnectTimeout(long connectTimeout) {
if (connectTimeout < 0)
throw new IllegalArgumentException("retryCount must > 0");
mConnectTimeout = connectTimeout;
getOkHttpClientBuilder().connectTimeout(connectTimeout, TimeUnit.MILLISECONDS);
return this;
}
/**
* 逾時重試次數
*/
public YcRetrofitUtils setRetryCount(int retryCount) {
if (retryCount < 0)
throw new IllegalArgumentException("retryCount must > 0");
mRetryCount = retryCount;
return this;
}
/**
* 逾時重試次數
*/
public static int getRetryCount() {
return getInstance().mRetryCount;
}
/**
* 逾時重試延遲時間
*/
public YcRetrofitUtils setRetryDelay(int retryDelay) {
if (retryDelay < 0)
throw new IllegalArgumentException("retryDelay must > 0");
mRetryDelay = retryDelay;
return this;
}
/**
* 逾時重試延遲時間
*/
public static int getRetryDelay() {
return getInstance().mRetryDelay;
}
/**
* 逾時重試延遲疊加時間
*/
public YcRetrofitUtils setRetryIncreaseDelay(int retryIncreaseDelay) {
if (retryIncreaseDelay < 0)
throw new IllegalArgumentException("retryIncreaseDelay must > 0");
mRetryIncreaseDelay = retryIncreaseDelay;
return this;
}
/**
* 逾時重試延遲疊加時間
*/
public static int getRetryIncreaseDelay() {
return getInstance().mRetryIncreaseDelay;
}
/**
* 全局設定baseurl
*/
public YcRetrofitUtils setBaseUrl(String baseUrl) {
mBaseUrl = checkNotNull(baseUrl, "baseUrl == null");
return this;
}
/**
* 擷取全局baseurl
*/
public static String getBaseUrl() {
return getInstance().mBaseUrl;
}
/**
* 根據目前的請求參數,生成對應的OkClient
*/
private OkHttpClient.Builder generateOkClient() {
if (mConnectTimeout <= 0)
setConnectTimeout(DEFAULT_MILLISECONDS);
if (mReadTimeOut <= 0)
setReadTimeOut(DEFAULT_MILLISECONDS);
if (mWriteTimeOut <= 0)
setWriteTimeOut(DEFAULT_MILLISECONDS);
if (mInterceptor == null) {
//由于Retrofit是基于okhttp的是以,要先初始化okhttp相關配置
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
// BASIC,BODY,HEADERS
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//添加攔截器
addOkHttpInterceptor(interceptor);
}
return getOkHttpClientBuilder();
}
/**
* 根據目前的請求參數,生成對應的Retrofit
*/
private Retrofit.Builder generateRetrofit() {
final Retrofit.Builder retrofitBuilder = getRetrofitBuilder().baseUrl(checkNotNull(getBaseUrl(), "baseUrl == null"));
if (mConverterFactory == null)
addConverterFactory(GsonConverterFactory.create());
if (mCallAdapterFactory == null)
addCallAdapterFactory(RxJava2CallAdapterFactory.create());
return retrofitBuilder;
}
/**
* 生成網絡請求build請求體
*
* @return
*/
public YcRetrofitUtils build() {
OkHttpClient.Builder okHttpClientBuilder = generateOkClient();
final Retrofit.Builder retrofitBuilder = generateRetrofit();
retrofitBuilder.client(okHttpClientBuilder.build());
if (retrofit == null) {
retrofit = retrofitBuilder.build();
}
return this;
}
public YcRetrofitUtils create() {
mBaseApiService = create(BaseApiService.class);
return this;
}
/**
* 建立api服務 可以支援自定義的api,預設使用BaseApiService,上層不用關心
*
* @param service 自定義的apiservice class
*/
public <T> T create(final Class<T> service) {
retrofit = checkNotNull(retrofit, "請先在調用build()才能使用");
return retrofit.create(service);
}
public static <T> T checkNotNull(T t, String message) {
if (t == null) {
throw new NullPointerException(message);
}
return t;
}
/**
* 添加參數
* 根據傳進來的Object對象來判斷是String還是File類型的參數
*/
public YcRetrofitUtils addParameter(String key, Object o) {
if (params != null && params.size() > 0)
clear();
if (o instanceof String) {
RequestBody body = RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), (String) o);
params.put(key, body);
} else if (o instanceof File) {
RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"), (File) o);
params.put(key + "\"; filename=\"" + ((File) o).getName() + "", body);
}
return this;
}
/**
* 建構RequestBody
*/
public Map<String, RequestBody> bulider() {
return params;
}
public void clear() {
params.clear();
}
/**
* get
*
* @param url 連結
* @param callBackListener 回調監聽
*/
public static void get(String url, final OnCallBackListener callBackListener) {
get(url, "", callBackListener);
}
/**
* get
*
* @param url 連結
* @param tag 類型
* @param callBackListener 回調監聽
*/
public static void get(String url, String tag, final OnCallBackListener callBackListener) {
Flowable flowable = mBaseApiService.get(url);
requestCallBack(flowable, tag, callBackListener);
}
/**
* get
*
* @param url 連結
* @param map 參數
* @param callBackListener 回調監聽
*/
public static void get(String url, Map map, final OnCallBackListener callBackListener) {
get(url, map, "", callBackListener);
}
/**
* get
*
* @param url 連結
* @param map 參數
* @param tag 類型
* @param callBackListener 回調監聽
*/
public static void get(String url, Map map, String tag, final OnCallBackListener callBackListener) {
Flowable flowable = mBaseApiService.get(url, map);
requestCallBack(flowable, tag, callBackListener);
}
/**
* post
*
* @param url 連結
* @param map 參數
* @param callBackListener 回調監聽
*/
public static void post(String url, Map map, final OnCallBackListener callBackListener) {
Flowable flowable = mBaseApiService.post(url, map);
requestCallBack(flowable, "", callBackListener);
}
/**
* post
*
* @param url 連結
* @param map 參數
* @param callBackListener 回調監聽
* @param tag 調用的方法類型(區分調用的方法的回調參數)
*/
public static void post(String url, Map map, String tag, final OnCallBackListener callBackListener) {
Flowable flowable = mBaseApiService.post(url, map);
requestCallBack(flowable, tag, callBackListener);
}
//===============================================================
/**
* 處理資料請求相關功能,将flowable加入隊列,通過接口回調的方式将rxjava傳回的資料傳回給調用者
*
* @param flowable 調入的flowable
* @param callBackListener 回調
* @param <T> 泛型參數
*/
public static <T> void requestCallBack(Flowable<T> flowable, final OnCallBackListener callBackListener) {
requestCallBack(flowable, "", callBackListener);
}
/**
* 處理資料請求相關功能,将flowable加入隊列,通過接口回調的方式将rxjava傳回的資料傳回給調用者
*
* @param callBackListener 回調
* @param tag 調用方法标志,回調用
* @param <T> 泛型參數
*/
public static <T> void requestCallBack(Flowable<T> flowable, final String tag, final OnCallBackListener callBackListener) {
sDisposableSubscriber = requestCallBack(tag, callBackListener);
onSubscribe(flowable, sDisposableSubscriber);
}
public static <T> DisposableSubscriber requestCallBack(final String tag, final OnCallBackListener callBackListener) {
sDisposableSubscriber = new DisposableSubscriber<T>() {
@Override
public void onNext(T body) {
try {
if (body instanceof ResponseBody) {
String response = ((ResponseBody) body).string();
callBackListener.onSuccess(response, tag);
} else {
callBackListener.onSuccess(body, tag);
}
} catch (Exception e) {
e.printStackTrace();
callBackListener.onFailed(e.getMessage().toString(), tag);
}
}
@Override
public void onError(Throwable t) {
callBackListener.onFailed(t.getMessage().toString(), tag);
}
@Override
public void onComplete() {
}
};
return sDisposableSubscriber;
}
public static <T> void onSubscribe(Flowable<T> flowable) {
onSubscribe(flowable, sDisposableSubscriber);
}
public static <T> void onSubscribe(Flowable<T> flowable, DisposableSubscriber<T> disposableSubscriber) {
Flowable<T> beanFlowable = flowable.subscribeOn(Schedulers.io());
beanFlowable.observeOn(AndroidSchedulers.mainThread())
.retryWhen(new RetryExceptionFunc(mRetryCount, mRetryDelay, mRetryIncreaseDelay))
.subscribeWith(disposableSubscriber);
}
/**
* 取消訂閱
*/
public static void cancelSubscription() {
cancelSubscription(sDisposableSubscriber);
}
/**
* 取消訂閱
*/
public static void cancelSubscription(Disposable disposable) {
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
逾時相關工具:
/**
* <p>描述:網絡請求錯誤重試條件</p>
*/
public class RetryExceptionFunc implements Function<Flowable<? extends Throwable>, Flowable<?>> {
/* retry次數*/
private int count = 0;
/*延遲*/
private long delay = 500;
/*疊加延遲*/
private long increaseDelay = 3000;
public RetryExceptionFunc() {
}
public RetryExceptionFunc(int count, long delay) {
this.count = count;
this.delay = delay;
}
public RetryExceptionFunc(int count, long delay, long increaseDelay) {
this.count = count;
this.delay = delay;
this.increaseDelay = increaseDelay;
}
@Override
public Flowable<?> apply(Flowable<? extends Throwable> flowable) throws Exception {
return flowable.zipWith(Flowable.range(1, count + 1), new BiFunction<Throwable, Integer, Wrapper>() {
@Override
public Wrapper apply(Throwable throwable, Integer integer) throws Exception {
return new Wrapper(throwable, integer);
}
}).flatMap(new Function<Wrapper, Publisher<?>>() {
@Override
public Publisher<?> apply(Wrapper wrapper) throws Exception {
if ((wrapper.throwable instanceof ConnectException
|| wrapper.throwable instanceof SocketTimeoutException
|| wrapper.throwable instanceof ConnectTimeoutException
|| wrapper.throwable instanceof SocketTimeoutException
|| wrapper.throwable instanceof TimeoutException)
&& wrapper.index < count + 1) { //如果超出重試次數也抛出錯誤,否則預設是會進入onCompleted
return Flowable.timer(delay + (wrapper.index - 1) * increaseDelay, TimeUnit.MILLISECONDS);
}
return Flowable.error(wrapper.throwable);
}
});
}
private class Wrapper {
private int index;
private Throwable throwable;
public Wrapper(Throwable throwable, int index) {
this.index = index;
this.throwable = throwable;
}
}
}
4.定義回調監聽接口
public interface OnRequestCallBackListener<T> {
void onSuccess(T result, String type);
void onFailed(String e, String type);
}
5.使用方法:
get方法:
Map map = new HashMap();
map.put("key", "你自己的key");
map.put("type", "top");
RetrofitUtils.getInstance().get(UrlConfig.NEWS_URL, map, new OnRequestCallBackListener<ResponseBody>() {
@Override
public void onSuccess(ResponseBody result, String type) {
try {
NewsBean newsBean = new Gson().fromJson(result.string(), NewsBean.class);
List<NewsBean.ResultBean.DataBean> data = newsBean.getResult().getData();
//通過回調将資料傳回給 model層
callBackListener.onSuccess(data);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailed(String e, String type) {
callBackListener.onFailed(e);
}
});
post方法:
RetrofitUtils instance = RetrofitUtils.getInstance();
instance.addParameter("key", "你自己的key");
instance.addParameter("type", "top");
Map<String, RequestBody> bulider = instance.bulider();
instance.post(UrlConfig.NEWS_URL, bulider, new OnRequestCallBackListener<ResponseBody>() {
@Override
public void onSuccess(ResponseBody result, String type) {
NewsBean newsBean = new Gson().fromJson(result.string(), NewsBean.class);
List<NewsBean.ResultBean.DataBean> data = newsBean.getResult().getData();
//通過回調将資料傳回給 model層
callBackListener.onSuccess(data);
}
@Override
public void onFailed(String e, String type) {
callBackListener.onFailed(e);
}
});
上傳圖文:
RetrofitUtils instance = RetrofitUtils.getInstance();
File file = new File(mImagePath);
instance.addParameter("avatar", file);
instance.addParameter("key", "你自己的key");
instance.addParameter("type", "top");
Map<String, RequestBody> bulider = instance.bulider();
instance.post(UrlConfig.NEWS_URL, bulider, new OnRequestCallBackListener<ResponseBody>() {
@Override
public void onSuccess(ResponseBody result, String type) {
try {
NewsBean newsBean = new Gson().fromJson(result.string(), NewsBean.class);
List<NewsBean.ResultBean.DataBean> data = newsBean.getResult().getData();
//通過回調将資料傳回給 model層
callBackListener.onSuccess(data);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailed(String e, String type) {
callBackListener.onFailed(e);
}
});
你也可以自定義自己的api
public interface BasicUseService {
//方式一
@GET("{path}")
Flowable<NewsBean> login(@Path("path") String path, @QueryMap Map<String, String> maps);
//方式二
@GET()
Flowable<NewsBean> login1(@Url String url, @QueryMap Map<String, String> maps);
//方式三
@GET("toutiao/index")
Flowable<NewsBean> login2(@QueryMap Map<String, String> maps);
}
用法:
mMap = new HashMap();
mMap.put("key", "4a216a3fde4361f175aa2678dada199b");
mMap.put("type", "top");
// BasicUseService basicUseService = YcRetrofitUtils.getRetrofit().create(BasicUseService.class);
Flowable login = basicUseService.login("toutiao/index", mMap);
YcRetrofitUtils.requestCallBack(login, "", new OnCallBackListener() {
@Override
public <Q> void onSuccess(Q body, String tag) {
if (body instanceof NewsBean) {
Toast.makeText(MainActivity.this, body.toString(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailed(String e, String tag) {
}
});
在addParameter方法中會根據傳入的velue 來判斷是傳入的是string 字元串還是 file 檔案
此方式有一個弊端就是 沒有用到retrofit 轉換bean的方式
使用方式看起來就是這麼簡單,這裡注意的是url采用的是傳參的方式,并沒有用base中注解的方式,可根據需要進行修改
以上就是,安卓架構搭建(六)Retrofit網絡請求(簡單封裝),的全部内容
如有不了解的 可以去github下載下傳源碼 本章節内容為分支6 (由于後期優化,分支6不是最新代碼,最新的可到主分支檢視網絡封裝,或到 YcRetrofitUtils源碼中 檢視具體内容)
github源碼位址,本章節見dev6分支
或 加入安卓開發交流群:安卓幫595856941
相關連結:
下一篇:
安卓架構搭建(七)BaseAdapter的封裝