亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android中volley封裝實踐記錄

2019-10-21 21:25:48
字體:
來源:轉載
供稿:網友

前言

在項目中一般使用使用volley方式如下,用起來給人一種很亂的感覺,于是一種盤它的想法油然而生。

public void get() {String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=......";StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {   @Override   public void onResponse(String s) {    Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show();   }  }, new Response.ErrorListener() {   @Override   public void onErrorResponse(VolleyError volleyError) {    Toast.makeText(MainActivity.this,volleyError.toString(),Toast.LENGTH_SHORT).show();   }  });  request.setTag("abcGet");  MyApplication.getHttpQueues().add(request); }

首先看一下我封裝后的使用例子:

 private void initData() {  NewsApi.getInfo(new NetCallback<News>() {   @Override   public void OnSuccess(final News result) {    mAdapter.setData(result.getResult().getData());   }   @Override   public void OnError(RestfulError error) {   }  }); }

有沒有看起來很舒服的感覺。好吧,讓我開始盤它吧!

1.首先我先去寫了一個基類,用來創建一個新的request并把它加入到volley內部封裝的請求隊列中,代碼如下:

public abstract class AuthenticatedRequestBase<T> extends Request<T> { private final static String TAG = "AuthenticatedRequestBase"; private static final int TIME_OUT = 30000; private static final int MAX_RETRIES = 1; private static final float BACKOFF_MULT = 2f; protected Context mContext; protected RequestQueue mRequestQueue; /**  * 創建新的請求,并把請求加入到請求隊列requestQueue中  *  * @param method  * @param url  * @param cache  * @param errorListener  */ @SuppressLint("LongLogTag") public AuthenticatedRequestBase(int method, String url, boolean cache, Response.ErrorListener errorListener) {  super(method, url, errorListener);  //this.setShouldCache(cache);  this.setRetryPolicy(new DefaultRetryPolicy(    TIME_OUT,    MAX_RETRIES,    BACKOFF_MULT));  mRequestQueue = YZ.getInstance().getRequestQueue();  if (mRequestQueue == null) {   throw new IllegalArgumentException("mRequestQueue can't be null");  }  mContext = YZ.getInstance().getContext();  if (mContext == null) {   throw new IllegalArgumentException("mContext can't be null");  }  //如果重新發出服務器請求的時候,需要清除之前的緩存。  if (!cache) {   Cache volleyCache = mRequestQueue.getCache();   Cache.Entry cacheEntry = volleyCache.get(url);   if (cacheEntry != null) {    volleyCache.remove(url);    Log.d(TAG, "remove volley cache:" + url);   }  }  mRequestQueue.add(this); } /**  * 重寫這個方法,可以在http請求頭里面加入token,客戶端能接受的數據類型  *  * @return  * @throws AuthFailureError  */ @CallSuper @Override public Map<String, String> getHeaders() throws AuthFailureError {  Map<String, String> headers = new HashMap<>();  String token = "............";  //headers.put("Authorization", "bearer " + token);  //針對Get方法,申明接受的enum類型  // headers.put("Accept", "charset=utf-8");  return headers; } /**  * 網絡錯誤問題統一處理  *  * @param volleyError  * @return  */ @CallSuper @Override protected VolleyError parseNetworkError(VolleyError volleyError) {  return super.parseNetworkError(volleyError); }}

代碼注釋比較清晰,就不在贅述。

2.以get方法為例,新建一個GetRequest去繼承這個基類,并出解析結果:

public class GetRequest<TResponse> extends AuthenticatedRequestBase<TResponse> { private final Response.Listener<TResponse> listener; private final Class<TResponse> clazz; private final static String TAG = "GetRequest"; private String mUrl; private NetCallback<TResponse> cb; private boolean cacheHit; public GetRequest(String url, Class<TResponse> clazz, boolean cache, NetCallback<TResponse> callback) {  super(Request.Method.GET, url, cache, callback.getErrorListener());  this.listener = callback.getSuccessListener();  this.clazz = clazz;  this.mUrl = url;  this.cb = callback;  //無網絡時300ms后返回callback  if (!NetUtils.isConnect(mContext) && mRequestQueue.getCache().get(url) == null) {   Handler handler = new Handler();   handler.postDelayed(new Runnable() {    @Override    public void run() {     cb.OnNetworkOff();    }   }, 300);  } } /**  * 這個是緩存的標記,與本地緩存相關  * @param tag  */ @Override public void addMarker(String tag) {  super.addMarker(tag);  cacheHit = tag.equals("cache-hit"); } @Override protected Response<TResponse> parseNetworkResponse(NetworkResponse response) {  Gson gson = new Gson();  //無網絡時,使用本地緩存,通過url去匹配緩存,volley sdk是通過url創建不同的文件來實現緩存的  if (!NetUtils.isConnect(mContext) && mRequestQueue.getCache().get(mUrl) != null) {   String json = new String(mRequestQueue.getCache().get(mUrl).data);   Log.d(TAG, "url==" + mUrl + ",json" + json);   cb.fResponseCacheStatus = ResponseCacheStatus.StaleFromCache;   return Response.success(gson.fromJson(json, clazz), parseCacheHeaders(response));  }  //數據是否有更新  try {   if (response.statusCode == 304) {    //服務端返回緩存數據    cb.fResponseCacheStatus = ResponseCacheStatus.NotModifiedFromServer;   } else if (response.statusCode == 200) {    if (cacheHit) {     //使用本地緩存     cb.fResponseCacheStatus = ResponseCacheStatus.FreshFromCache;    } else {     //使用服務端更新數據     cb.fResponseCacheStatus = ResponseCacheStatus.NewFromServer;    }   } else {    cb.fResponseCacheStatus = ResponseCacheStatus.NewFromServer;   }   Log.d(TAG, "fResponseCacheStatus = " + cb.fResponseCacheStatus);   String json = new String(response.data, parseCharset(response.headers));   return Response.success(gson.fromJson(json, clazz), parseCacheHeaders(response));  } catch (UnsupportedEncodingException | JsonSyntaxException e) {   return Response.error(new ParseError(e));  } } @Override protected void deliverResponse(TResponse response) {  listener.onResponse(response); } @Override protected VolleyError parseNetworkError(VolleyError volleyError) {  return super.parseNetworkError(volleyError); }}

3.上面只做了返回成功的處理方式,返回失敗時由NetCallback內部統一處理:

@UiThreadpublic abstract class NetCallback<TResponse> { public ResponseCacheStatus fResponseCacheStatus = ResponseCacheStatus.NewFromServer; private String TAG = this.getClass().getSimpleName(); public boolean enableAutomaticToastOnError = true; public NetCallback() { } public NetCallback(boolean enableAutomaticToastOnError) {  this.enableAutomaticToastOnError = enableAutomaticToastOnError; } public abstract void OnSuccess(TResponse result); public abstract void OnError(RestfulError error); public void OnNetworkOff() {  //do nothing ,use it according to requirement } public Response.Listener<TResponse> getSuccessListener() {  return new Response.Listener<TResponse>() {   @Override   public void onResponse(TResponse result) {    OnSuccess(result);   }  }; } public Response.ErrorListener getErrorListener() {  return new Response.ErrorListener() {   @Override   public void onErrorResponse(VolleyError volleyError) {    if (volleyError instanceof TimeoutError) {     Log.e(TAG, "networkResponse == null");     //volley TimeoutError     OnError(new RestfulError());    }    if (volleyError.networkResponse != null) {     int statusCode = volleyError.networkResponse.statusCode;     String errorMessage = new String(volleyError.networkResponse.data);     switch (statusCode) {      case 401:       //post a Permission authentication failed event       break;      default:       Log.d(TAG, "errorMessage =" + errorMessage);       try {        RestfulError error = new Gson().fromJson(errorMessage, RestfulError.class);        if (enableAutomaticToastOnError && error.getCode() != null) {         //toast(error.ExceptionMessage); //toast it in main thread        }        OnError(error);       } catch (Exception e) {        OnError(new RestfulError());        Log.d(TAG, "e =" + e.toString());       }       break;     }    }   }  }; }}

4.注意到沒有,在AuthenticatedRequestBase內部有一個環境類YZ,主要負責獲取項目主程序中的context和請求隊列:

public class YZ implements AppRequestQueue { private static final int DEFAULT_VOLLEY_CACHE_SIZE = 100 * 1024 * 1024; private Context context; private int cacheSize; private YZ() { } @Override public RequestQueue getRequestQueue() {  return Volley.newRequestQueue(context, cacheSize); } public Context getContext() {  return context; } private static class SingletonHolder {  private static YZ instance = new YZ(); } public static YZ getInstance() {  return SingletonHolder.instance; } /**  * need a app context  *  * @param appContext  */ public void init(final Context appContext) {  init(appContext, DEFAULT_VOLLEY_CACHE_SIZE); } /**  * @param appContext  * @param cacheSize  */ public void init(final Context appContext, final int cacheSize) {  this.context = appContext;  this.cacheSize = cacheSize; }}

這個類需要在app的application中初始化:

public class BaseApp extends Application { public String TAG = this.getClass().getSimpleName(); public static Context applicationContext; public static Executor threadPool; public static final int THREAD_POOL_SIZE = 3; public static final boolean isDebug = BuildConfig.BUILD_TYPE.equals("debug"); @Override public void onCreate() {  super.onCreate();  applicationContext = getApplicationContext();  threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);  initNet(); } private void initNet() {  YZ.getInstance().init(this); } public Context getInstance() {  return applicationContext; }}

4.現在可以開始外部封裝啦。

public class NewsApi { public static void getInfo(NetCallback<News> callback) {  new GetRequest<>(INetConstant.NEWS, News.class, true, callback); }}

還有一點,volley的緩存實現需要服務端配合在http請求的Cache-control: max-age配置支持緩存,并設定好緩存時間,否則無法生效。

最后貼一張效果圖:

Android,volley,封裝

圖片發自簡書App

到此結束,后期還會進行優化,代碼在[github] (https://github.com/daydaydate/sample)。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久中文精品视频| 国产精品1234| 国内精品久久久久伊人av| 久久久欧美精品| 精品一区二区三区电影| 国产精品成人一区二区三区吃奶| 国产精品香蕉国产| 九九热精品在线| 揄拍成人国产精品视频| 国产日韩欧美一二三区| 国产精品网站大全| 亚洲国产另类久久精品| 精品视频久久久| 亚洲免费一在线| 欧美国产日韩一区二区| 欧美精品在线观看| 久久久久久久久久久免费精品| 国产精品99导航| 国产经典一区二区| 国产精品手机播放| 欧美日韩一区二区在线| 一道本无吗dⅴd在线播放一区| 久久成人精品一区二区三区| 亚洲人成电影网站色www| 91视频国产一区| 欧美日韩国产精品一区二区三区四区| 亚洲精品在线观看www| 亚洲欧美成人精品| 日韩精品在线免费观看| 庆余年2免费日韩剧观看大牛| 亚洲综合自拍一区| 精品无人区乱码1区2区3区在线| 色系列之999| 亚洲欧美日韩一区二区三区在线| 亚洲奶大毛多的老太婆| 日韩在线观看电影| 国产精品电影一区| 国产精品一区二区三区在线播放| 深夜福利国产精品| 91国在线精品国内播放| 国产精品美女www爽爽爽视频| 91精品国产综合久久男男| 国产精品吹潮在线观看| 欧美在线日韩在线| 欧美日韩激情视频8区| 日韩精品在线视频| 国产精品日韩在线观看| 亚洲欧美中文另类| 国产日韩一区在线| 成人在线观看视频网站| 久久99国产精品自在自在app| 色婷婷**av毛片一区| 欧美一级片一区| 精品毛片三在线观看| 成人免费直播live| 久久亚洲欧美日韩精品专区| 2021久久精品国产99国产精品| 日韩电影大全免费观看2023年上| 中国人与牲禽动交精品| 成人深夜直播免费观看| 91精品视频专区| 亚洲视频免费一区| 成人a免费视频| 亚洲伊人成综合成人网| 久久精彩免费视频| 欧美日韩一区二区免费在线观看| 91亚洲永久免费精品| 777午夜精品福利在线观看| 欧美一区二区三区精品电影| 日韩精品视频免费在线观看| 国产在线精品成人一区二区三区| 久久精品国产精品| 国产v综合v亚洲欧美久久| 国产成人在线播放| 成人激情视频在线播放| 欧美在线视频一区| 国产99视频精品免视看7| 亚洲天堂成人在线| 久久99热这里只有精品国产| 伊人久久大香线蕉av一区二区| 国产一区二区三区在线视频| 91精品在线看| 亚洲成人av片在线观看| 国产精品久久二区| 91欧美视频网站| 91色视频在线导航| 亚洲人a成www在线影院| 一区二区成人av| 国产精品一区久久久| 国产精品久久在线观看| 8x海外华人永久免费日韩内陆视频| 懂色av一区二区三区| 庆余年2免费日韩剧观看大牛| 亚洲淫片在线视频| 91精品国产自产91精品| 亚洲日本欧美中文幕| 亚洲iv一区二区三区| 久久人人爽人人爽爽久久| 国产成人+综合亚洲+天堂| 久久精品国产一区二区电影| 亚洲高清久久网| 欧美疯狂xxxx大交乱88av| 不卡在线观看电视剧完整版| 日韩精品在线第一页| 有码中文亚洲精品| 精品视频久久久久久| 精品亚洲一区二区三区| 亚洲国产精品高清久久久| 亚洲午夜av电影| 亚洲人线精品午夜| 欧美一区二区.| 国产精品高清在线观看| 亚洲一区亚洲二区| 国产aⅴ夜夜欢一区二区三区| 久久777国产线看观看精品| 在线观看欧美视频| 欧美在线视频a| 国产一区二区三区在线看| 欧美老肥婆性猛交视频| 国产精品入口免费视频一| 91av在线免费观看| 亚洲性xxxx| 亚洲第一精品夜夜躁人人爽| 岛国av一区二区在线在线观看| 国产精品69久久| 亚洲欧美国产精品久久久久久久| 国产精品第二页| 成人福利网站在线观看11| 亚洲国产精品成人va在线观看| www日韩中文字幕在线看| 日韩一中文字幕| 国产精品视频公开费视频| 国产精品99蜜臀久久不卡二区| 日韩av综合中文字幕| 国产亚洲一区二区在线| 亚洲欧洲xxxx| 中文字幕亚洲天堂| 国产色婷婷国产综合在线理论片a| 欧美理论片在线观看| 欧美第一淫aaasss性| 亚洲女同性videos| 91精品久久久久久久久久入口| 91亚洲精品久久久| 久久久人成影片一区二区三区观看| 91美女高潮出水| 日韩av不卡在线| 中文字幕在线看视频国产欧美| 色先锋久久影院av| 色婷婷亚洲mv天堂mv在影片| 日韩在线观看成人| 亚洲欧美制服综合另类| 亚洲精选中文字幕| 欧美午夜视频在线观看| 成人免费在线视频网站| 日韩av免费看网站| 精品久久久国产精品999| 久久欧美在线电影| 亚洲区bt下载| 精品久久久久久久久国产字幕| 国产日韩av在线播放| 欧美成人精品不卡视频在线观看| 久久亚洲成人精品| 久久久久久12| 亚洲激情中文字幕|