返回顶部
首页 > 资讯 > 精选 >OKHttp3(支持Retrofit)的网络数据缓存Interceptor拦截器的实现
  • 766
分享到

OKHttp3(支持Retrofit)的网络数据缓存Interceptor拦截器的实现

okhttpinterceptorce 2023-05-30 17:05:25 766人浏览 独家记忆
摘要

前言:前段时间在开发APP的时候,经常出现由于用户设备环境的原因,拿不到从网络端获取的数据,所以在APP端展现的结果总是一个空白的框,这种情况对于用户体验来讲是极其糟糕的,所以,苦思冥想决定对OKHttp下手(因为我在项目中使用的网络请求框

前言:前段时间在开发APP的时候,经常出现由于用户设备环境的原因,拿不到从网络端获取的数据,所以在APP端展现的结果总是一个空白的框,这种情况对于用户体验来讲是极其糟糕的,所以,苦思冥想决定对OKHttp下手(因为我在项目中使用的网络请求框架就是OKHTTP),则 写了这么一个网络数据缓存拦截器。
OK,那么我们决定开始写了,我先说一下思路:

思路篇

既然要写的是网络数据缓存拦截器,主要是利用了OKHTTP强大的拦截器功能,那么我们应该对哪些数据进行缓存呢,或者在哪些情况下启用数据进行缓存机制呢?

第一 :支持POST请求,因为官方已经提供了一个缓存拦截器,但是有一个缺点,就是只能对GET请求的数据进行缓存,对POST则不支持。

第二 :网络正常的时候,则是去网络端取数据,如果网络异常,比如TimeOutException UnKnowHostException 诸如此类的问题,那么我们就需要去缓存取出数据返回。

第三 :如果从缓存中取出的数据是空的,那么我们还是需要让这次请求走剩下的正常的流程。

第四 :调用者必须对缓存机制完全掌控,可以根据自己的业务需求选择性的对数据决定是否进行缓存。

第五 :使用必须简单,这是最最最最重要的一点。

好,我们上面罗列了五点是我们的大概思路,现在来说一下代码部分:

代码篇

缓存框架 :我这里使用的缓存框架是DiskLruCache https://GitHub.com/JakeWharton/DiskLruCache 这个缓存框架可以存储到本地,也经过谷歌认可,这也是选择这个框架的主要原因。我这里也对缓存框架进行封装了一个CacheManager类:

import Android.content.Context;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import com.xiaolei.OkhttpCacheInterceptor.Log.Log;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlGorithmException;public class CacheManager{  public static final String TAG = "CacheManager";  //max cache size 10mb  private static final long DISK_CACHE_SIZE = 1024 * 1024 * 10;  private static final int DISK_CACHE_INDEX = 0;  private static final String CACHE_DIR = "responses";  private DiskLruCache mDiskLruCache;  private volatile static CacheManager mCacheManager;  public static CacheManager getInstance(Context context)  {    if (mCacheManager == null)    {      synchronized (CacheManager.class)      {        if (mCacheManager == null)        {          mCacheManager = new CacheManager(context);        }      }    }    return mCacheManager;  }  private CacheManager(Context context)  {    File diskCacheDir = getDiskCacheDir(context, CACHE_DIR);    if (!diskCacheDir.exists())    {      boolean b = diskCacheDir.mkdirs();      Log.d(TAG, "!diskCacheDir.exists() --- diskCacheDir.mkdirs()=" + b);    }    if (diskCacheDir.getUsableSpace() > DISK_CACHE_SIZE)    {      try      {        mDiskLruCache = DiskLruCache.open(diskCacheDir,            getAppVersion(context), 1, DISK_CACHE_SIZE);        Log.d(TAG, "mDiskLruCache created");      } catch (IOException e)      {        e.printStackTrace();      }    }  }    public void putCache(String key, String value)  {    if (mDiskLruCache == null) return;    OutputStream os = null;    try    {      DiskLruCache.Editor editor = mDiskLruCache.edit(encryptMD5(key));      os = editor.newOutputStream(DISK_CACHE_INDEX);      os.write(value.getBytes());      os.flush();      editor.commit();      mDiskLruCache.flush();    } catch (IOException e)    {      e.printStackTrace();    } finally    {      if (os != null)      {        try        {          os.close();        } catch (IOException e)        {          e.printStackTrace();        }      }    }  }    public void setCache(final String key, final String value)  {    new Thread()    {      @Override      public void run()      {        putCache(key, value);      }    }.start();  }    public String getCache(String key)  {    if (mDiskLruCache == null)    {      return null;    }    FileInputStream fis = null;    ByteArrayOutputStream bos = null;    try    {      DiskLruCache.Snapshot snapshot = mDiskLruCache.get(encryptMD5(key));      if (snapshot != null)      {        fis = (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX);        bos = new ByteArrayOutputStream();        byte[] buf = new byte[1024];        int len;        while ((len = fis.read(buf)) != -1)        {          bos.write(buf, 0, len);        }        byte[] data = bos.toByteArray();        return new String(data);      }    } catch (IOException e)    {      e.printStackTrace();    } finally    {      if (fis != null)      {        try        {          fis.close();        } catch (IOException e)        {          e.printStackTrace();        }      }      if (bos != null)      {        try        {          bos.close();        } catch (IOException e)        {          e.printStackTrace();        }      }    }    return null;  }    public void getCache(final String key, final CacheCallback callback)  {    new Thread()    {      @Override      public void run()      {        String cache = getCache(key);        callback.onGetCache(cache);      }    }.start();  }    public boolean removeCache(String key)  {    if (mDiskLruCache != null)    {      try      {        return mDiskLruCache.remove(encryptMD5(key));      } catch (IOException e)      {        e.printStackTrace();      }    }    return false;  }    private File getDiskCacheDir(Context context, String uniqueName)  {    String cachePath = context.getCacheDir().getPath();    return new File(cachePath + File.separator + uniqueName);  }    public static String encryptMD5(String string)  {    try    {      byte[] hash = MessageDigest.getInstance("MD5").digest(          string.getBytes("UTF-8"));      StringBuilder hex = new StringBuilder(hash.length * 2);      for (byte b : hash)      {        if ((b & 0xFF) < 0x10)        {          hex.append("0");        }        hex.append(Integer.toHexString(b & 0xFF));      }      return hex.toString();    } catch (NoSuchAlgorithmException | UnsupportedEncodingException e)    {      e.printStackTrace();    }    return string;  }    private int getAppVersion(Context context)  {    PackageManager pm = context.getPackageManager();    try    {      PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);      return pi == null ? 0 : pi.versionCode;    } catch (PackageManager.NameNotFoundException e)    {      e.printStackTrace();    }    return 0;  }}

--结束END--

本文标题: OKHttp3(支持Retrofit)的网络数据缓存Interceptor拦截器的实现

本文链接: https://lsjlt.com/news/220261.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作