欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android 中Volley二次封裝并實現(xiàn)網絡請求緩存

 更新時間:2017年09月06日 11:54:34   作者:Danny_姜  
這篇文章主要介紹了Android 中Volley二次封裝并實現(xiàn)網絡請求緩存的相關資料,希望通過本文能幫助到大家,徹底會使用Volley,需要的朋友可以參考下

Android 中Volley二次封裝并實現(xiàn)網絡請求緩存

Android目前很多同學使用Volley請求網絡數(shù)據(jù),但是Volley沒有對請求過得數(shù)據(jù)進行緩存,因此需要我們自己手動緩存。 一下就是我的一種思路,僅供參考

具體使用方法為:

HashMap<String,String> params = new HashMap<>();
params.put("id", "1");
params.put("user", "mcoy");
new NetWorkHelper(getActivity()).jacksonMethodRequest
("method_id", params, new TypeReference<ReturnTemple<FirstCategories>>(){}, handler, msgId);

NetWorkHelper---對Volley的封裝,首先調用CacheManager.get(methodName, params);方法獲取緩存中的數(shù)據(jù),如果數(shù)據(jù)為null,

則繼續(xù)發(fā)送網絡請求。

/** 
 * @version V1.0 網絡請求幫助類 
 * @author: mcoy 
 */ 
public final class NetWorkHelper { 
 
  private NetWorkManager netWorkUtils; 
 
  public NetWorkHelper(Context context){ 
    netWorkUtils = new NetWorkManager(context); 
  } 
 
  public static final String COMMON_ERROR_MSG = "連接超時,請稍后重試"; 
  public static final int COMMON_ERROR_CODE = 2; 
 
 
  /** 
   * 使用Jackson請求的方法 
   * @param methodName 
   * @param params 
   * @param handler 
   * @param msgId 
   */ 
  public void jacksonMethodRequest(final String methodName,final HashMap<String,String> params,TypeReference javaType, final Handler handler,final int msgId){ 
 
    ResponseListener listener =  new ResponseListener(){ 
      @Override 
      public void onResponse(Object response, boolean isCache) { 
        PrintLog.log(response.toString()); 
        if (isCache){ 
          CacheManager.put(methodName, params, response); 
        } 
        if (handler != null) { 
          Message message = handler.obtainMessage(); 
          message.what = msgId; 
          message.obj = response; 
          handler.sendMessage(message); 
        } 
      } 
    }; 
 
    Object respone = CacheManager.get(methodName, params); 
    if(respone != null){ 
      listener.onResponse(respone,false); 
      return; 
    } 
 
    HashMap<String,String> allParams = Config.setSign(true); 
    allParams.putAll(params); 
    Response.ErrorListener errorListener = new Response.ErrorListener() { 
      @Override 
      public void onErrorResponse(VolleyError error) { 
        error.printStackTrace(); 
        if (handler != null) { 
          Message message = handler.obtainMessage(); 
          message.what = msgId; 
          message.obj = COMMON_ERROR_MSG; 
          handler.sendMessage(message); 
        } 
      } 
    }; 
    netWorkUtils.jacksonRequest(getUrl(methodName), allParams,javaType, listener, errorListener); 
  } 
 
  /** 
   * Url直接請求 
   * @param url 
   * @param params 
   * @param handler 
   * @param msgId 
   */ 
  public void urlRequest(String url,HashMap<String,String> params,JsonParser jsonParser,final Handler handler,final int msgId){ 
 
    request(url, true, params, jsonParser, handler, msgId); 
  } 
 
  /** 
   * 通過方法請求 
   * @param methodName 方法名 
   * @param params 請求參數(shù) 
   * @param jsonParser Json解析器 
   * @param handler 回調通知 
   * @param msgId 通知的Id 
   */ 
  public void methodRequest(String methodName, final HashMap<String,String> params,final JsonParser jsonParser,final Handler handler,final int msgId){ 
    request(getUrl(methodName),true,params,jsonParser,handler,msgId); 
  } 
 
  /** 
   * 通過方法請求 
   * @param methodName 方法名 
   * @param params 請求參數(shù) 
   * @param jsonParser Json解析器 
   * @param handler 回調通知 
   * @param msgId 通知的Id 
   */ 
  public void methodRequest(String methodName, boolean isLogin,final HashMap<String,String> params,final JsonParser jsonParser,final Handler handler,final int msgId){ 
    request(getUrl(methodName),isLogin,params,jsonParser,handler,msgId); 
  } 
 
 
 
 
  private void request(final String url, boolean isLogin,final HashMap<String,String> params,final JsonParser jsonParser,final Handler handler,final int msgId){ 
    final HashMap<String,String> allParams = Config.setSign(isLogin); 
    allParams.putAll(params); 
    Response.Listener listener = new Response.Listener<String>() { 
      @Override 
      public void onResponse(String response) { 
        /** 
         * 有些請求默認是沒有parser傳過來的,出參只求String,譬如聯(lián)合登錄等 
         * 所以加了一個else if 
         */ 
        Object result; 
        PrintLog.log(response); 
        if (jsonParser != null ) { 
          jsonParser.json2Obj(response); 
          jsonParser.temple.description = jsonParser.temple.getResultDescription(); 
          result = jsonParser.temple; 
        } else { 
          ReturnTemple temple = new ReturnTemple(); 
          temple.issuccessful = false; 
          temple.description = COMMON_ERROR_MSG; 
          temple.result = -100; 
          result = temple; 
        } 
        if (handler != null) { 
          Message message = handler.obtainMessage(); 
          message.what = msgId; 
          message.obj = result; 
          handler.sendMessage(message); 
        } 
      } 
    }; 
 
    Response.ErrorListener errorListener = new Response.ErrorListener() { 
      @Override 
      public void onErrorResponse(VolleyError error) { 
        Object result; 
        if (jsonParser != null) { 
          ReturnTemple temple = new ReturnTemple(); 
          temple.issuccessful = false; 
          temple.description = COMMON_ERROR_MSG; 
          temple.result = COMMON_ERROR_CODE; 
          result = temple; 
        } else { 
          result = COMMON_ERROR_MSG; 
        } 
        if (handler != null) { 
          Message message = handler.obtainMessage(); 
          message.what = msgId; 
          message.obj = result; 
          handler.sendMessage(message); 
        } 
      } 
    }; 
    netWorkUtils.request(url, allParams, listener, errorListener); 
  } 
 
  /** 
   * 根據(jù)訪求名拼裝請求的Url 
   * @param methodName 
   * @return 
   */ 
  private String getUrl(String methodName){ 
    String url = Config.getUrl(); 
    if (!StringUtil.isNullOrEmpty(methodName)) { 
      url = url + "?method=" + methodName; 
    } 
    return url; 
  } 
} 

CacheManager---將針對某一method所請求的數(shù)據(jù)緩存到本地文件當中,主要是將CacheRule寫到本地文件當中

/** 
 * @version V1.0 <緩存管理> 
 * @author: mcoy 
 */ 
public final class CacheManager { 
  /** 
   * 一個方法對應的多個Key,比如分類都是同一個方法,但是請求會不一樣,可能都要緩存 
   */ 
  private static HashMap<String, ArrayList<String>> methodKeys; 
  private static final String keyFileName = "keys.pro"; 
 
  /** 
   * 讀取緩存的Key 
   */ 
  public static void readCacheKey() { 
    methodKeys = (HashMap<String, ArrayList<String>>) readObject(keyFileName); 
    if (methodKeys == null) { 
      methodKeys = new HashMap<String, ArrayList<String>>(); 
    } 
  } 
 
  /** 
   * 保存緩存 
   */ 
  public static void put(String method, HashMap<String, String> params, Object object) { 
    long expireTime = CacheConfig.getExpireTime(method); 
    if (expireTime <= 0 || methodKeys == null) {//有效時間小于0,則不需要緩存 
      return; 
    } 
    String key = createKey(method, params); 
    if (methodKeys.containsKey(method)) { 
      ArrayList<String> keys = methodKeys.get(method); 
      keys.add(key); 
    } else { 
      ArrayList<String> keys = new ArrayList<>(); 
      keys.add(key); 
      methodKeys.put(method, keys); 
    } 
    writeObject(methodKeys, keyFileName); 
    String fileName = key + ".pro"; 
    CacheRule cacheRule = new CacheRule(expireTime, object); 
    LogModel.log(" put " + method + " " + key + " " + cacheRule); 
    writeObject(cacheRule, fileName); 
  } 
 
  public static Object get(String method, HashMap<String, String> params) { 
    long expireTime = CacheConfig.getExpireTime(method); 
    if (expireTime <= 0 || methodKeys == null || !methodKeys.containsKey(method)) {//有效時間小于0,則不需要緩存 
      return null; 
    } 
    ArrayList<String> keys = methodKeys.get(method); 
//    String saveKey = keys.get(method); 
    String key = createKey(method, params); 
    String fileName = key + ".pro"; 
//    LogModel.log("get"+method+" "+(saveKey.equals(key))+" path:"+fileName); 
 
    CacheRule cacheRule = null; 
    try { 
      if (keys.contains(key)) { 
        cacheRule = (CacheRule) readObject(fileName); 
      } 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
    LogModel.log("get :" + method + " " + key + " " + cacheRule); 
    if (cacheRule != null && cacheRule.isExpire()) { 
      return cacheRule.getData(); 
    } else { 
      return null; 
    } 
  } 
 
 
  public static void main(String[] args) { 
    String method = "category.getCategory"; 
    HashMap<String, String> params = new HashMap<>(); 
    params.put("categoryId", "-3"); 
    System.out.println(createKey(method, params)); 
    System.out.println(CacheRule.getCurrentTime()); 
  } 
 
  /** 
   * 生成Key 
   * 
   * @param method 請求的方法名 
   * @param params 私有參數(shù)(除公共參數(shù)以外的參數(shù)) 
   * @return 
   */ 
  private static String createKey(String method, HashMap<String, String> params) { 
    try { 
      MessageDigest digest = MessageDigest.getInstance("md5"); 
      digest.digest(method.getBytes("UTF-8")); 
      StringBuilder builder = new StringBuilder(method); 
      if (params != null && params.size() > 0) { 
        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator(); 
        while (iterator.hasNext()) { 
          Map.Entry<String, String> entry = iterator.next(); 
          builder.append(entry.getKey()).append("=").append(entry.getValue()); 
        } 
      } 
      byte[] tempArray = digest.digest(builder.toString().getBytes("UTF-8")); 
      StringBuffer keys = new StringBuffer(); 
      for (byte b : tempArray) { 
        // 與運算 
        int number = b & 0xff;// 加鹽 
        String str = Integer.toHexString(number); 
        // System.out.println(str); 
        if (str.length() == 1) { 
          keys.append("0"); 
        } 
        keys.append(str); 
      } 
      return keys.toString().toUpperCase(); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
    return method.toUpperCase(); 
  } 
 
  /** 
   * 將對象寫到文件中 
   * 
   * @param object 
   * @param fileName 
   */ 
  private static void writeObject(Object object, String fileName) { 
    try { 
      ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File(CacheConfig.getCachePath() + fileName))); 
      oo.writeObject(object); 
      oo.close(); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
  } 
 
  /** 
   * 讀取對象 
   * 
   * @param fileName 
   * @return 
   */ 
  private static Object readObject(String fileName) { 
    Object result = null; 
    try { 
      File file = new File(CacheConfig.getCachePath() + fileName); 
      if (file.exists()) { 
        ObjectInputStream oi = new ObjectInputStream(new FileInputStream(file)); 
        result = oi.readObject(); 
        oi.close(); 
      } 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
    return result; 
  } 
} 

CacheConfig---初始化哪些方法需要做緩存處理,以及緩存的有效時間

/** 
 * @version V1.0 <設置哪些類數(shù)據(jù)需要緩存> 
 
 * @author: mcoy 
 */ 
public final class CacheConfig { 
  /**方法對應的緩存有效時間,時間是毫秒*/ 
  private static HashMap<String,Long> methodExpireTimes = new HashMap<String, Long>(); 
  private static String cachePath = null; 
 
  static { 
    methodExpireTimes.put(ConstMethod.GET_CATEGORY_LIST,30 * 60 * 1000L); 
    methodExpireTimes.put(ConstMethod.GET_NEW_CATEGORY_LIST,30 * 60 * 1000L); 
  } 
 
  /** 
   * 初始化緩存路徑 
   * @param context 
   */ 
  public static void init(Context context){ 
    cachePath = context.getFilesDir().getPath()+ File.separator+"cache"+File.separator; 
    File file = new File(cachePath); 
    if(!file.exists()){ 
      file.mkdirs(); 
    } 
    CacheManager.readCacheKey(); 
  } 
 
  /**緩存路徑*/ 
  public static String getCachePath() { 
    return cachePath; 
  } 
 
  /** 
   * 獲取有方法對應的有效時間,如果方法沒有添加緩存或者緩存時間小于0,則不添加緩存 
   * @param method 
   * @return 
   */ 
  public static long getExpireTime(String method){ 
    if(methodExpireTimes.containsKey(method)){ 
      return methodExpireTimes.get(method); 
    }else { 
      return -1; 
    } 
  } 
} 

CacheRule---主要有兩個參數(shù),expireTime需要緩存的時間, data需要緩存的數(shù)據(jù)

public class CacheRule implements Serializable{ 
  /** 有效時間 */ 
  public long expireTime; 
  /** 緩存時間*/ 
  public long cacheTime; 
  /** 緩存數(shù)據(jù) */ 
  private Object data; 
 
  public CacheRule(long expireTime,Object data){ 
    cacheTime = getCurrentTime(); 
    this.expireTime = expireTime; 
    this.data = data; 
  } 
 
  public Object getData() { 
    return data; 
  } 
 
  public void setData(Object data) { 
    this.data = data; 
  } 
 
  @Override 
  public int hashCode() { 
    return BeanTools.createHashcode(expireTime, cacheTime, data); 
  } 
 
  @Override 
  public String toString() { 
    StringBuilder builder = new StringBuilder(); 
    builder.append("expireTime:").append(expireTime).append(" cacheTime:").append(cacheTime) 
        .append(" curTime:").append(getCurrentTime()) 
        .append(" isExpire:").append(isExpire()).append(" data:").append(data==null?"null":data.toString()); 
    return builder.toString(); 
  } 
 
  /** 
   * 數(shù)據(jù)是否有效 
   * @return 
   */ 
  public boolean isExpire(){ 
    long curTime = getCurrentTime(); 
    return curTime>(expireTime+cacheTime)?false:true; 
  } 
 
  /** 
   * 獲取當前時間 
   * @return 
   */ 
  public static long getCurrentTime(){ 
//    if (Build.VERSION_CODES.JELLY_BEAN_MR1 <= Build.VERSION.SDK_INT) { 
//      return SystemClock.elapsedRealtimeNanos(); 
//    } else { 
      return System.currentTimeMillis(); 
//    } 
  } 
} 

NetWorkManager---往RequestQueue中添加JacksonRequest請求,然后Volley會去請求數(shù)據(jù)

/** 
 * 網絡請求的工具類 
 */ 
public final class NetWorkManager { 
 
 
  private RequestQueue requestQueue ; 
 
  public NetWorkManager(Context context){ 
    requestQueue = Volley.newRequestQueue(context); 
  } 
 
 
 
 
  /** 
   * 使用Jackson解析請求的方法 
   * @param url 
   * @param params 
   * @param javaType 成功時返回的Java類型 
   * @param listener 
   * @param errorListener 
   */ 
  public void jacksonRequest(final String url,final HashMap<String,String> params,TypeReference javaType, ResponseListener listener, Response.ErrorListener errorListener){ 
    JacksonRequest jacksonRequest = new JacksonRequest(url,javaType,params,listener,errorListener); 
    requestQueue.add(jacksonRequest); 
  } 
 
  /** 
   * 普通的網絡請求,返回的Json 
   * @param url 
   * @param params 
   * @param listener 
   * @param errorListener 
   */ 
  public void request(final String url,final HashMap<String,String> params,Response.Listener listener,Response.ErrorListener errorListener){ 
 
    StringRequest stringRequest = new StringRequest(Request.Method.POST,url,listener,errorListener){ 
      @Override 
      protected Map<String, String> getParams() throws AuthFailureError { 
        if (PrintLog.DEBUG) { 
          Iterator<Map.Entry<String,String>> iterator = params.entrySet().iterator(); 
          StringBuilder builder = new StringBuilder(url+" "); 
          while (iterator.hasNext()){ 
            Map.Entry<String,String> entry = iterator.next(); 
            builder.append(entry.getKey()+":"+entry.getValue()).append("; "); 
          } 
          PrintLog.log(builder.toString()); 
        } 
        return params; 
      } 
    }; 
    requestQueue.add(stringRequest); 
  } 
 
 
} 

JacksonRequest---繼承Request,重寫deliverResponse方法,并調用ResponseListener的onResponse方法,并通過CacheManager.put(methodName, params, response);將獲取的response緩存到CacheManager中。這一步很重要,調用我們自己的listener,而不是Volley提供給我們的Response.Listener

/** 
 * Created by mcoy 
 */ 
public class JacksonRequest extends Request { 
  private final HashMap<String,String> params; 
  private final ResponseListener listener; 
  private final ObjectMapper mapper; 
  private final TypeReference javaType; 
 
  public JacksonRequest(String url,TypeReference javaType,HashMap<String,String> params,ResponseListener listener,Response.ErrorListener errorListener){ 
    super(Method.POST,url,errorListener); 
    mapper = new ObjectMapper(); 
    mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES,true); 
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
    this.params = params; 
    this.listener = listener; 
    this.javaType = javaType; 
  } 
 
  @Override 
  protected Map<String, String> getParams() throws AuthFailureError { 
    return params; 
  } 
 
  @Override 
  protected Response parseNetworkResponse(NetworkResponse response) { 
    String json; 
    try { 
      json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 
      PrintLog.log("返回的json:" + json); 
      return Response.success(mapper.readValue(json,javaType), HttpHeaderParser.parseCacheHeaders(response)); 
    }catch (UnsupportedEncodingException e){ 
      json = new String(response.data); 
      PrintLog.log("json:"+json); 
      try { 
        return Response.success(mapper.readValue(json,javaType),HttpHeaderParser.parseCacheHeaders(response)); 
      } catch (IOException e1) { 
        return Response.error(new ParseError(e)); 
      } 
    } catch (JsonParseException e) { 
      PrintLog.log(e.toString()); 
      return Response.error(new ParseError(e)); 
    } catch (JsonMappingException e) {PrintLog.log(e.toString()); 
      return Response.error(new ParseError(e)); 
    } catch (IOException e) {PrintLog.log(e.toString()); 
      return Response.error(new ParseError(e)); 
    } 
  } 
 
  @Override 
  protected void deliverResponse(Object response) { 
    listener.onResponse(response,true); 
  } 
 
} 

ResponseListener---自定義的一個listener接口, 在發(fā)送請求時,需要將其實現(xiàn)。其中才參數(shù)中比Volley的提供的listener過了一個isCache的Boolean值,根據(jù)此值來決定是否要緩存。

/** 
 * @version V1.0 <描述當前版本功能> 
 * @author: mcoy 
 */ 
public interface ResponseListener<T> { 
  public void onResponse(T response, boolean isCache); 
} 

如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關文章

  • Android中WindowManager與WMS的解析

    Android中WindowManager與WMS的解析

    今天小編就為大家分享一篇關于Android中WindowManager與WMS的解析,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • android studio實現(xiàn)簡單的計算器(無bug)

    android studio實現(xiàn)簡單的計算器(無bug)

    這篇文章主要為大家詳細介紹了android studio實現(xiàn)簡單計算器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • android實現(xiàn)icon動態(tài)旋轉效果

    android實現(xiàn)icon動態(tài)旋轉效果

    這篇文章主要為大家詳細介紹了android實現(xiàn)icon動態(tài)旋轉效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Android 往Framework中添加新資源的方法詳解

    Android 往Framework中添加新資源的方法詳解

    本篇文章是對Android往Framework中添加新資源的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-06-06
  • Android自定義View實現(xiàn)豎向滑動回彈效果

    Android自定義View實現(xiàn)豎向滑動回彈效果

    這篇文章主要為大家詳細介紹了Android自定義View實現(xiàn)滑動回彈效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Android仿淘寶預訂日歷(18)

    Android仿淘寶預訂日歷(18)

    這篇文章主要為大家詳細介紹了Android仿淘寶預訂日歷的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Kotlin協(xié)程之Flow基礎原理示例解析

    Kotlin協(xié)程之Flow基礎原理示例解析

    這篇文章主要為大家介紹了Kotlin協(xié)程之Flow基礎原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Android 數(shù)據(jù)庫SQLite 寫入SD卡的方法

    Android 數(shù)據(jù)庫SQLite 寫入SD卡的方法

    如果手機沒有root,數(shù)據(jù)庫文件是無法查看到的,不方便調試。最好的辦法是把數(shù)據(jù)庫寫進SD卡。通過本文給大家介紹Android 數(shù)據(jù)庫SQLite 寫入SD卡的方法,需要的朋友參考下吧
    2016-04-04
  • Android實現(xiàn)掃碼功能

    Android實現(xiàn)掃碼功能

    這篇文章主要為大家詳細介紹了Android實現(xiàn)掃碼功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Android IPC進程間通信詳解最新AndroidStudio的AIDL操作)

    Android IPC進程間通信詳解最新AndroidStudio的AIDL操作)

    這篇文章主要介紹了Android IPC進程間通信的相關資料,需要的朋友可以參考下
    2016-09-09

最新評論