Android开发之App缓存管理

聊一聊:内存优化的目的是什么? 在开始之前需要先搞明白一个问题,为什么要做内存优化?或者说做内存优化的目的是什么?内存优化的主要目的是提高应用程序运行的效率和性能,并减少应用程序由于内存问题导致的崩溃或者卡顿情况。当一个应用程序运行时,它需要通过系统申请一部分内存空间来存储程序数据,但是如果这部分内存空间使用过多,就会导致整个系统内存的不稳定以及其他应用程序的运行受到影响。因此,通过对Android应用程序内存空间的管理和优化,可以使得应用程序运行更加顺畅,提高应用程序的响应速度和性能,并且可以避免由于内存不足导致的崩溃或者卡顿情况。 阅读详情

无论大型或小型应用,灵活的缓存可以说不仅大大减轻了服务器的压力,而且因为更快速的用户体验而方便了用户。
Android的apk可以说是作为小型应用,其中99%的应用并不是需要实时更新的,而且诟病于蜗牛般的移动网速,与服务器的数据交互是能少则少,这样用户体验才更好,这也是我们有时舍弃webview而采用json传输数据的原因之一。
采用缓存,可以进一步大大缓解数据交互的压力,特此,我们简略列举一下缓存管理的适用环境:

  1. 提供网络服务的应用
  2. 数据更新不需要实时更新,但是哪怕是3-5分钟的延迟也是可以采用缓存机制。
  3. 缓存的过期时间是可以接受的(不会因为缓存带来的好处,导致某些数据因为更新不及时而影响产品的形象等)
    带来的好处:
  4. 服务器的压力大大减小
  5. 客户端的响应速度大大变快(用户体验)
  6. 客户端的数据加载出错情况大大较少,大大提高了应有的稳定性(用户体验)
  7. 一定程度上可以支持离线浏览(或者说为离线浏览提供了技术支持)

一、缓存管理的方法

这里的缓存管理的原理很简:通过时间的设置来判断是否读取缓存还是重新下载。
里面会有一些细节的处理,后面会详细阐述。
基于这个原理,目前鄙人见过的两种比较常见的缓存管理方法是:数据库法和文件法。

二、数据库法缓存管理

这种方法是在下载完数据文件后,把文件的相关信息如url,路经,下载时间,过期时间等存放到数据库,下次下载的时候根据url先从数据库中查询,如果查询到当前时间并未过期,就根据路径读取本地文件,从而实现缓存的效果。
从实现上我们可以看到这种方法可以灵活存放文件的属性,进而提供了很大的扩展性,可以为其它的功能提供一定的支持;
从操作上需要创建数据库,每次查询数据库,如果过期还需要更新数据库,清理缓存的时候还需要删除数据库数据,稍显麻烦,而数据库操作不当又容易出现一系列的性能,ANR问题,实现的时候要谨慎,具体作的话,但也只是增加一个工具类或方法的事情。
还有一个问题,缓存的数据库是存放在/data/data//databases/目录下,是占用内存空间的,如果缓存累计,容易浪费内存,需要及时清理缓存。
当然这种方法从目前一些应用的实用上看,我没有发现什么问题。
本文我侧重强调第二种方法,第一种方法的实现,就此掠过。

三、文件法缓存管理

这种方法,使用File.lastModified()方法得到文件的最后修改时间,与当前时间判断是否过期,从而实现缓存效果。
实现上只能使用这一个属性,没有为其它的功能提供技术支持的可能。
操作上倒是简单,比较时间即可。本身处理也不容易带来其它问题,代价低廉。

四、文件法缓存管理的两点说明

1、不同类型的文件的缓存时间不一样。
笼统的说,不变文件的缓存时间是永久,变化文件的缓存时间是最大忍受不变时间。
说白点,图片文件内容是不变的,直到清理,我们是可以永远读取缓存的。
配置文件内容是可能更新的,需要设置一个可接受的缓存时间。
2、不同环境下的缓存时间标准不一样。
无网络环境下,我们只能读取缓存文件,哪怕缓存早就过期。
WiFi网络环境下,缓存时间可以设置短一点,一是网速较快,而是流量不要钱。
移动数据流量环境下,缓存时间可以设置长一点,节省流量,就是节省金钱,而且用户体验也更好。
这个时间根据自己的实际情况来设置:数据的更新频率,数据的重要性等。

五、何时刷新

开发者一方面希望尽量读取缓存,用户一方面希望实时刷新,但是响应速度越快越好,流量消耗越少越好,是一个矛盾。
其实何时刷新我也不知道,这里我提供两点建议:
1、数据的最长多长时间不变,对应用无大的影响。
如果你觉得数据比较重要或者比较受欢迎,用户会经常把玩,再减少,1~2小时,依次类推。
为了保险起见,你可能需要毫无理由的再次缩减一下。
2、提供刷新按钮。
上面说的保险起见不一定保险,最保险的方法使在相关界面提供一个刷新按钮,为缓存,为加载失败提供一次重新来过的机会,有了这个刷新按钮,我们的心也才真的放下来。

六、文件缓存法的具体实现

针对配置文件的缓存,我新建了一个类ConfigCache:

import java.io.File;
import java.io.IOException;
 
import android.util.Log;
 
import com.tianxia.app.floworld.AppApplication;
import com.tianxia.app.floworld.utils.FileUtils;
import com.tianxia.app.floworld.utils.NetworkUtils;
 
public class ConfigCache {
    private static final String TAG = ConfigCache.class.getName();
 
    public static final int CONFIG_CACHE_MOBILE_TIMEOUT  = 3600000;  //1 hour
    public static final int CONFIG_CACHE_WIFI_TIMEOUT    = 300000;   //5 minute
 
    public static String getUrlCache(String url) {
        if (url == null) {
            return null;
        }
 
        String result = null;
        File file = new File(AppApplication.mSdcardDataDir + "/" + getCacheDecodeString(url));
        if (file.exists() && file.isFile()) {
            long expiredTime = System.currentTimeMillis() - file.lastModified();
            Log.d(TAG, file.getAbsolutePath() + " expiredTime:" + expiredTime/60000 + "min");
            //1. in case the system time is incorrect (the time is turn back long ago)
            //2. when the network is invalid, you can only read the cache
            if (AppApplication.mNetWorkState != NetworkUtils.NETWORN_NONE && expiredTime < 0) {
                return null;
            }
            if(AppApplication.mNetWorkState == NetworkUtils.NETWORN_WIFI
                   && expiredTime > CONFIG_CACHE_WIFI_TIMEOUT) {
                return null;
            } else if (AppApplication.mNetWorkState == NetworkUtils.NETWORN_MOBILE
                   && expiredTime > CONFIG_CACHE_MOBILE_TIMEOUT) {
                return null;
            }
            try {
                result = FileUtils.readTextFile(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
 
    public static void setUrlCache(String data, String url) {
        File file = new File(AppApplication.mSdcardDataDir + "/" + getCacheDecodeString(url));
        try {
            //创建缓存数据到磁盘,就是创建文件
            FileUtils.writeTextFile(file, data);
        } catch (IOException e) {
            Log.d(TAG, "write " + file.getAbsolutePath() + " data failed!");
            e.printStackTrace();
        }
    }
 
    public static String getCacheDecodeString(String url) {
        //1. 处理特殊字符
        //2. 去除后缀名带来的文件浏览器的视图凌乱(特别是图片更需要如此类似处理,否则有的手机打开图库,全是我们的缓存图片)
        if (url != null) {
            return url.replaceAll("[.:/,%?&=]", "+").replaceAll("[+]+", "+");
        }
        return null;
    }
}
  从实现上我们全面考虑了几个细节,注释已经说明,不再赘述。
  然后我们调用方法如下:
void getConfig(){
        //首先尝试读取缓存
        String cacheConfigString = ConfigCache.getUrlCache(CONFIG_URL);
        //根据结果判定是读取缓存,还是重新读取
        if (cacheConfigString != null) {
            showConfig(cacheConfigString);
        } else {
            //如果缓存结果是空,说明需要重新加载
            //缓存为空的原因可能是1.无缓存;2. 缓存过期;3.读取缓存出错
            AsyncHttpClient client = new AsyncHttpClient();
            client.get(CONFIG_URL, new AsyncHttpResponseHandler(){
 
                @Override
                public void onSuccess(String result){
                    //成功下载,则保存到本地作为后面缓存文件
                    ConfigCache.setUrlCache(result,  CONFIG_URL);
                    //后面可以是UI更新,仅供参考
                    showConfig(result);
                }
 
                @Override
                public void onFailure(Throwable arg0) {
                    //根据失败原因,考虑是显示加载失败,还是再读取缓存
                }
 
            });
        }
    }

这样配置文件既能有效缓存,又能及时更新了,同时支持离线浏览。

OBD协议探秘——J1850 PWM与VPW实战解码 当时仪表盘亮着发动机故障灯,我用普通OBD-II扫描工具却怎么也读不出故障码,后来才知道这类美系老车用的是特殊的J1850协议。有趣的是,我在拆解一辆2005年的马自达时,意外发现它用的也是PWM协议——这算是日系车里的"美式特供"。在车库折腾到凌晨是常有的事,但每次成功解码出那些"会说话"的脉冲时,那种成就感就像破译了汽车的摩斯密码。最近发现SDS1104X-E示波器的序列触发功能特别适合捕捉J1850的SOF(帧起始标志),PWM的SOF是48μs高电平,VPW则是200μs高电平。 阅读详情

相关推荐

【UV打印机】PrintExp打印软件教程(六)-高级模式(马达)

输入高级模式密码进入高级模式高级模式界面有操作栏、控制栏、参数栏及参数界面操作栏名称功能说明文件加载数据从板卡加载参数保存将参数保存到主板退出退出高级模式固件导入固件导入配套版本下的固件配置*xpcfx导出固件导出当前使用的固件配置*xpcfx导入波形文件导入对应的波形文件*waf操作初始化系统继续初始化动作复位X轴复位回原点控制栏可进行小车运动、闪喷操作(此闪喷为点击进行闪喷,不受平台位置限制),无清洗功能。

Print World的专栏 3112

Android-APP内存优化

为什么要进行内存优化 APP运行内存限制,OOM导致APP崩溃 APP性能:流畅性、响应速度和用户体验

不要錯過才珍惜 6688

金属粘结剂喷射3D打印技术:工艺流程与后处理关键

金属粘结剂喷射(Binder Jetting)是一种创新的增材制造技术,通过逐层喷射粘合剂将金属粉末粘结成型,再经过脱脂和烧结等后处理工序获得最终零件。这项技术的核心优势在于无需支撑结构、可实现批量生产,并且材料利用率高。在3D打印领域,金属BJ技术特别适合中小尺寸、结构复杂且表面质量要求高的零件生产。其工艺流程包括前期数据处理、打印生胚阶段、拆包与清粉,以及关键的渗透、脱脂和烧结后处理环节。后处理工艺的控制直接决定了零件的机械性能和尺寸精度,其中烧结工艺尤为关键,需要精确控制温度曲线和气氛环境。金属BJ打

weixin_35751194的博客 86

Android学习系列(27)--App缓存管理

无论大型或小型应用,灵活的缓存可以说不仅大大减轻了服务器的压力,而且因为更快速的用户体验而方便了用户。Android的apk可以说是作为小型应用,其中99%的应用并不是需要实时更新的,而且诟病于蜗牛般的移动网速,与服务器的数据交互是能少则少,这样用户体验才更好,这也是我们有时舍弃webview而采用json传输数据的原因之一。采用缓存,可以进一步大大缓解数据交互的压力,特此,我们简略列...

dianan1505的博客 539

详细解读文字识别工具———Tesseract-OCR

   在尝试破解12306验证码的时候,提前了解了一下应对各种验证码的解决方案,这里主要是学习到了面对文字图片验证码,例如亚马逊、豆瓣等平台的登录时会遇到的情况,效果还不错。 一、工具介绍 ​    Tesseract-OCR 是一款由HP实验室开发由Google维护的开源OCR(Optical Character Recognition...

别看我只是一只羊 2万+

Vivado2022.2下载安装

链接:https://pan.baidu.com/s/1lyfE2d-VmaWC-_aR8ratCQ提取码:mt09。

weixin_61081689的博客 2万+

Android性能优化之内存优化

Android系统虚拟机的垃圾回收是通过虚拟机GC机制来实现的。GC会选择一些还存活的对象作为内存遍历的根节点GC Roots,通过对GC Roots的可达性来判断是否需要回收。内存泄漏就是在当前应用周期内不再使用的对象被GC Roots引用,导致不能回收,使实际可使用内存变小。例如,在onDraw方法里面不要执行对象的创建,一般来说,都应该在自定义View的构造器中创建对象。

2401_83642079的博客 1778

UE5 C++教程(一、基本结构)

虚幻API由三块组成,分别是Runtime,Developer utilitiew,functionality for the Editor,大多数游戏性编程只使用运行时模块,最常见的三个是Corn、CornUObject和Engine。

skycol的博客 1万+

android 开发常用的工具类

转自大牛博客 https://blankj.com/ 他的工具类github https://github.com/Blankj https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/README-CN.md 目录: Activity 相关 -> ActivityUtils.java getActivityByVi...

skyang在路上 1442

【工具使用】Keil常用的调试操作整理介绍

2、当选择了非0级优化时,调试可能会变得困难,具体表现在断点调试。该按钮是在进入了函数单步调试的时候,有时候你可能不必再执行该函数的剩余部分了,通过该按钮就直接一步执行完函数余下的部分,并跳出函数,回到函数被调用的置。:如果是在C语言窗口中,则是按单条语句执行,与单步调试不同的是,遇到函数不会进入函数内部,而是直接全速运行函数,并跳到下一条语句。但我的Keil软件中无法显示这个视图,并且通过修改系统试图,调试时,点击打开系统视图发生了闪退的现象,目前能想到的原因是:重新安装Keil,安装最新版本。

MEYOU_Cc 不吃香菜! 1万+

记录LeNet的硬件加速器设计(一)

LeNet的硬件加速器设计实现。

2301_81029398的博客 3544

Android 最强大的工具类blankj:utilcode

github地址:https://github.com/Blankj/AndroidUtilCode Download Gradle: implementation ‘com.blankj:utilcode:1.23.2’ APIs Activity 相关 -> ActivityUtils.java -> Demo getActivityByView : 根据...

fancky58的博客 8004

【WRF-Urban运行】WRF-SLUCM耦合建模参数设置及模拟运行

WRF-SLUCM耦合建模参数设置及模拟运行

WW、forever的博客 1724

Android开发人员不得不收集的代码(持续更新中)

Download Gradle: 1 2 3 4 implementation 'com.blankj:utilcode:1.28.0' // if u use AndroidX, use the following implementation 'com.blankj:utilcodex:1.28.0' APIs Activit...

feelinghappy的专栏 695

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

AndroidUtilCode 介绍和使用

AndroidUtilCode 是一个强大易用的安卓工具类库,它合理地封装了安卓开发中常用的函数,具有完善的 Demo 和单元测试,利用其封装好的 APIs 可以大大提高开发效率,如今它主要包括两部分模块,其一是主工具类模块:utilcode,其中的工具类是开发中常用到的;其二是子工具类模块:subutil,它包含的工具类并不是很常用,它的出现是为了防止主工具类的臃肿。 Documentation utilcode使用: Gradle: implementation '...

huangjunjie1991的专栏 1463

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

android 强大的工具库utilCode

github链接 Download Gradle: implementation 'com.blankj:utilcode:1.23.7' // if u use AndroidX, use the following implementation 'com.blankj:utilcodex:1.23.7' APIs Activity 相关 ->ActivityUt...

wqbs369的专栏 1万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Android这可能是当今最火,功能最全的快速开发框架了

今天给大家介绍一款功能最全,使用最方便的Android快速开发框架传送门:GitHub-AndroidUtilCode首先添加Gradle:compile 'com.blankj:utilcode:1.9.8'在Application中进行初始化Utils.init(application);混淆-keep class com.blankj.utilcode.** { *; } -keepclass

Augustine的博客 1万+

android好博客

app集成支付宝、app缓存管理、app列表圆角设计、App自动更新之通知栏下载(有续)、索引ListView、App数据格式之解析Json、拖拽ListView  http://www.cnblogs.com/qianxudetianxia/category/293007.html http://www.cnblogs.com/xiaoQLu/archive/2012/07/...

weixin_33907511的博客 86

安卓学习教程

稍微整理下Android学习系列的文章目录 Android学习系列(1)--App签名(为apk签名) Android学习系列(2)--App自动更新之通知栏下载 Android学习系列(3)--App自动更新之自定义进度视图和内部存储 Android学习系列(4)--App自适应draw9patch不失真背景 Android学习系列(5)--App布局初探之简单模型 Android学...

weixin_30575309的博客 88

分享一个牛哄哄的Android工具集合类

分享一个Android工具集合类,基本我们开发要用到的基本操作这里边基本全部囊括了,github地址:https://github.com/Blankj/AndroidUtilCodeDownloadGradle:compile 'com.blankj:utilcode:1.13.5'How to use// init it in the function of onCreate in ur Ap...

Tongseng‘s Blog 2105

Android开发人员不得不收集的工具类代码

Android开发人员不得不收集的工具类代码Android开发人员不得不收集的工具类代码 https://github.com/Blankj/AndroidUtilCode/blob/master/README-CN.md API Activity相关→ActivityUtils.java→Demo isActivityExists : 判断是否存在Activity sta

天山一客 的专栏 1547

Android安卓天气预报系统设计与实现.zip(论文+导入项目教程+项目源码)

.项目总体设计 1.1 系统需求分析 本次项目是开发一款基于Androi平台的天气预报app,通过利用现有的网络开源API提供的服务快速获取天气信息并显示到手机终端上,该app所需要实现的功能点: (1)、显示当前城市当日天气; (2)、显示当前城市未来三天天气; (3)、显示各项指数(如穿衣、运动等); (4)、通过城市列表管理城市; (5)、滑动屏幕切换城市; (6)、城市添加与删除; (7)、通过搜索城市名字添加城市; (8)、通过设置更改背景; (9)、清除app缓存; 项目的设计是通过图片和文字显

weixin_40228600的博客 1419

常用工具总结

http://www.jianshu.com/p/72494773aace http://pan.baidu.com/s/1gfrGBYV Activity相关→ActivityUtils.java→Demo isActivityExists : 判断是否存在Activity ...

chengniqie9367的博客 155

Android 14 正式发布,已经在 AOSP 中上线,快来看看有什么吧

等了这么久 Android 14 终于还是来了,当然其实并没有什么太惊喜的地方,反而需要适配和调整的又多了,如果你还没设配,或者不知道什么地方需要适配的,也可以看 Android 14 快速适配要点。Android 14 正式发布,已经在 AOSP 中上线,快来看看有什么吧。

chuyouyinghe的专栏 3159

Android开发人员不得不收集的代码(持续更新中)(http://www.jianshu.com/p/72494773aace,原链接)

Android开发人员不得不收集的代码(持续更新中) Blankj 关注 2016.07.31 04:22* 字数 370 阅读 102644评论 479喜欢 3033赞赏 14 utilcode Download Gradle: compile 'com.blankj:utilcode:1.9.6' How to use // init it in

qq_34095189的博客 751
上一篇: 快看,Android开发工程师都在学的kotlin秘籍出现了
下一篇: Flutter中的触摸事件
不秃头de程序猿
博客等级 码龄5年 4089粉丝 1478原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值