| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
LillaBaez
7年前发布

Android里巧妙实现缓存

   <p>为了快速查询会被多次调用的数据,或者构建比较废时的实例,我们一般使用缓存的方法。缓存的基本概念大体上差不多,这里就不再重复,有兴趣的可以查看维基百科的介绍。</p>    <p>缓存有很多的实现方式,技巧性还有坑都很多,今天我给大家介绍一些非通用的方法,可以巧妙地帮大家简单实现一些内存缓存。</p>    <h3><strong>Supplier和Memoize</strong></h3>    <p>SQLite是Android里常用的一种数据存储方式,在访问数据库数据时需要通过SQLiteOpenHelper。</p>    <p>一份好的数据库连接代码应该能解决以下几个问题: a) 构建实例比较费资源 b) 数据库连接最好能复用 c) onUpdate等方法在执行时不能和其他实例构成冲突。</p>    <p>这里可以很简单的这样写</p>    <pre>  <code class="language-java">Suppliers.memoize(new Supplier<SQLiteOpenHelper>() {      @Override    public SQLiteOpenHelper get() {      return new ...;    }  })</code></pre>    <p> </p>    <p>这段代码利用了Guava提供的一些辅助方法实现Supplier和Memoize和逻辑。顾名思义,Supplier一般被用作factory,generator,builder,closure。Memoize类似于缓存这种概念,它一旦生成了一个实例,在以后的调用中都会返回同一实例,而且,线程安全。</p>    <p>这样写有几个好处,一是需要时才去构建实例,并不会在一开始就去阻塞程序的执行,二是它很简单的用memoize实现了缓存,保证只有一个实例生成。</p>    <h3><strong>代码注入</strong></h3>    <p>Glow是代码注入的重度使用者,它使我们的代码更加结构化,清晰,简单,同时还节省了不少的开发时间。</p>    <p>Dagger 2是我们实现注入的刀具,有兴趣的同学应该去网站多了解一下相关的内容。除了注入,它还有一些附赠功能,而这些恰巧能被我们用来实现缓存,而且还很简单,我们只需要额外用到几个annotation或接口而已。</p>    <p><strong>@Singleton</strong></p>    <p>相信大家对这个应该比较熟悉,这可是面试时的常问问题。简单来说,它就是单例。因为所以,用了它你不用再担心对这些实例怎么实现缓存了吧。</p>    <pre>  <code class="language-java">@Singleton  public class SingletonClass {    }</code></pre>    <p><strong>@Reusable</strong></p>    <p>这是一个新的很酷的功能。单例虽然很好,但有些时候实例可能有些太大,一直放在内存,又不能回收,暂时可能程序也用不到,怎么都感觉有些浪费。很多情况下,我们并没有那么严格的要求需要唯一的一个实例,能重用就重用,没有重新实例化一个就行。这就是@Reusable的使用场景,假如已有一个生成的实例,重用它就行,不行重新实例化,不需要保证。</p>    <pre>  <code class="language-java">@Reusable  public class ReusableClass {    }</code></pre>    <p><strong>Lazy</strong></p>    <p>Lazy使用的地方和前两者有些不同。@Singleton和@Reusable一般用在provides或类型定义的地方,但Lazy则是用在使用时,它的使用效果和最开始讲到的Supplier和Memoize类似。</p>    <pre>  <code class="language-java">@Inject  Lazy<SQLiteOpenHelper> lazySQLiteOpenHelper;</code></pre>    <p>这里不会先生成SQLiteOpenHelper实例,直到你开始调用lazySQLiteOpenHelper.get()。而一旦第一次实例化结束,以后的调用都会返回第一次的结果。</p>    <h3><strong>Observable</strong></h3>    <p>在使用app的过程中,很多数据需要从服务器端获取。在我们app里,每天会为用户提供一些订制化内容,这些内容短期内不会改变,每次从服务器端去取太过耗时,但放到数据库或文件这些持久化存储里似乎不太必要。综合考虑后,似乎内存缓存是个不错的选择。</p>    <p>于是这个缓存需要提供以下功能,首先,它是个缓存,其次,它的结构需要很简单,因为很多地方需要用到,再次,它得线程安全。</p>    <p>后来我们的实现方案很简单,利用Retrofit和Observable提供的一些方法。</p>    <pre>  <code class="language-java">private static final long EXPIRE_MS = 5 * 60 * 1000;    private Pair<Long, Observable<Content>> cache;    public synchronized Observable<Content> getDailyContent() {      if (cache == null || cache.first + EXPIRE_MS < System.currentTimeMillis()) {        cache = Pair.create(System.currentTimeMillis(), serverApi.getContent());      }      return cache.second;    }</code></pre>    <p> </p>    <p>这个方法的本质是利用Retrofit返回的Observable对象,然后Observable会提供一个类似缓存的cache方法,这样在subscribe之前,这个网络请求不会被发出,但一旦有了结果,后来的调用者都会得到同样的结果。</p>    <p><strong>注意</strong></p>    <p>缓存虽好,用起来很快捷方便,但在使用过程中,大家一定要注意数据更新和线程安全,不要出现脏数据。</p>    <p> </p>    <p>来自:http://www.jointforce.com/jfperiodical/article/3516</p>    <p> </p>    
 本文由用户 LillaBaez 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
 转载本站原创文章,请注明出处,并保留原始链接、图片水印。
 本站是一个以用户分享为主的开源技术平台,欢迎各类分享!
 本文地址:https://www.open-open.com/lib/view/open1478660037149.html
数据库 安卓开发 Android开发 移动开发