Android温习 —— 内存

在Android开发中我们常常听到这样几个概念:内存内部存储外部存储,我时常将这几个概念搞混,今天在研究Glide框架源码时,又碰到了相关的问题,再次查阅了下资料,特此记录!!!

内存,我们在英文中称作 memory,亦即 运行内存 (简称 运存RAM);内部存储,我们称为 InternalStorage外部存储 我们称为 ExternalStorage,这在英文中本不会产生歧义,但是当我们翻译为中文之后,前两个都简称为 内存,于是,混了。
那么究竟什么是内部存储,而什么又是外部存储呢?
首先我们打开DDMS,有一个File Explorer,如下:
这里写图片描述
这里有三个文件夹需要我们重视:datamntstorage,我们下面就详细说说这三个文件夹。

内部存储(InternalStorage)

data 文件夹就是我们常说的内部存储,当我们打开 data 文件夹之后(没有root的手机不能打开该文件夹),里边有两个文件夹值得我们关注,如下:

这里写图片描述

一个文件夹是 APP 文件夹,还有一个文件夹就是 data 文件夹,APP 文件夹里存放着我们所有安装的 APPapk 文件,其实,当我们调试一个 APP 的时候,可以看到控制台输出的内容,有一项是 “uploading …..”,就是上传我们的 apk 到这个文件夹,上传成功之后才开始安装。另一个重要的文件夹就是 data 文件夹了,这个文件夹里边都是一些包名,打开这些包名之后我们会看到这样的一些文件:

  • data/data/包名/shared_prefs
  • data/data/包名/databases
  • data/data/包名/files
  • data/data/包名/cache

如果打开过 data 文件,应该都知道这些文件夹是干什么用的,我们在使用 SharedPreferenced 的时候,将数据持久化存储于本地,其实就是存在这个文件中的 XML 文件里,我们 APP 里边的数据库文件就存储于 databases 文件夹中,还有我们的普通数据存储在 files 文件夹中,缓存文件存储在 cache 文件夹中,存储在这里的文件我们都称之为内部存储。

外部存储(ExternalStorage)

外部存储才是我们平时操作最多的,外部存储 一般就是我们上面看到的 storage 文件夹,当然也有可能是 mnt 文件夹,这个不同厂家有可能不一样。
一般来说,在 storage 文件夹中有一个 sdcard 文件夹,这个文件夹中的文件又分为两类,一类是公有目录,还有一类是私有目录,其中的公有目录有九大类,比如 DCIMDOWNLOAD 等这种系统为我们创建的文件夹,私有目录就是 Android 这个文件夹,这个文件夹打开之后里边有一个 data 文件夹,打开这个 data 文件夹,里边有许多包名组成的文件夹。

Android是如何管理内存的

Android并不会在用户切换不同应用时候做交换内存的操作。Android会把那些不包含foreground组件的进程放到LRU cache中。例如,当用户刚开始启动了一个应用,系统会为它创建了一个进程,但是当用户离开这个应用,此进程并不会立即被销毁。系统会把这个进程放到cache中,如果用户后来再回到这个应用,此进程就能够被完整恢复,从而实现应用的快速切换。

如果你的应用中有一个被缓存的进程,这个进程会占用暂时不需要使用到的内存,这个暂时不需要使用的进程,它被保留在内存中,这会对系统的整体性能有影响。因此当系统开始进入低内存状态时,它会由系统根据LRU的规则与其他因素选择综合考虑之后决定杀掉某些进程,那么怎样保持你的进程能够尽可能长久的被缓存呢?

1) 珍惜Services资源

如果你的应用需要在后台使用service,除非它被触发并执行一个任务,否则其他时候service都应该是停止状态。另外需要注意当这个service完成任务之后因为停止service失败而引起的内存泄漏。

当你启动一个service,系统会倾向为了保留这个service而一直保留service所在的进程。这使得进程的运行代价很高,因为系统没有办法把service所占用的RAM空间腾出来让给其他组件,另外service还不能被paged out。这减少了系统能够存放到LRU缓存当中的进程数量,它会影响app之间的切换效率。它甚至会导致系统内存使用不稳定,从而无法继续保持住所有目前正在运行的service。

限制你的service的最好办法是使用IntentService, 它会在处理完交代给它的intent任务之后尽快结束自己。

2) 当UI隐藏时释放内存

当用户切换到其它应用并且你的应用 UI不再可见时,你应该释放你的应用UI上所占用的所有内存资源。在这个时候释放UI资源可以显著的增加系统缓存进程的能力,它会对用户体验有着很直接的影响。

为了能够接收到用户离开你的UI时的通知,你需要实现Activtiy类里面的onTrimMemory()回调方法。你应该使用这个方法来监听到TRIM_MEMORY_UI_HIDDEN级别的回调,此时意味着你的UI已经隐藏,你应该释放那些仅仅被你的UI使用的资源。

请注意:你的应用仅仅会在所有UI组件的被隐藏的时候接收到onTrimMemory()的回调并带有参数TRIM_MEMORY_UI_HIDDEN。这与onStop()的回调是不同的,onStop()会在activity的实例隐藏时会执行,例如当用户从你的app的某个activity跳转到另外一个activity时前面activity的onStop()会被执行。因此你应该实现onStop()回调,并且在此回调里面释放activity的资源,例如释放网络连接,注销监听广播接收者。除非接收到onTrimMemory(TRIM_MEMORY_UI_HIDDEN)的回调,否者你不应该释放你的UI资源。这确保了用户从其他activity切回来时,你的UI资源仍然可用,并且可以迅速恢复activity。

3) 当内存紧张时释放部分内存

在你的app生命周期的任何阶段,onTrimMemory的回调方法同样可以告诉你整个设备的内存资源已经开始紧张。你应该根据onTrimMemory回调中的内存级别来进一步决定释放哪些资源。

  • TRIM_MEMORY_RUNNING_MODERATE:你的app正在运行并且不会被列为可杀死的。但是设备此时正运行于低内存状态下,系统开始触发杀死LRU Cache中的Process的机制。

  • TRIM_MEMORY_RUNNING_LOW:你的app正在运行且没有被列为可杀死的。但是设备正运行于更低内存的状态下,你应该释放不用的资源用来提升系统性能(但是这也会直接影响到你的app的性能)。

  • TRIM_MEMORY_RUNNING_CRITICAL:你的app仍在运行,但是系统已经把LRU Cache中的大多数进程都已经杀死,因此你应该立即释放所有非必须的资源。如果系统不能回收到足够的RAM数量,系统将会清除所有的LRU缓存中的进程,并且开始杀死那些之前被认为不应该杀死的进程,例如那个包含了一个运行态Service的进程。

同样,当你的app进程正在被cached时,你可能会接受到从onTrimMemory()中返回的下面的值之一:

  • TRIM_MEMORY_BACKGROUND:系统正运行于低内存状态并且你的进程正处于LRU缓存名单中最不容易杀掉的位置。尽管你的app进程并不是处于被杀掉的高危险状态,系统可能已经开始杀掉LRU缓存中的其他进程了。你应该释放那些容易恢复的资源,以便于你的进程可以保留下来,这样当用户回退到你的app的时候才能够迅速恢复。

  • TRIM_MEMORY_MODERATE:系统正运行于低内存状态并且你的进程已经已经接近LRU名单的中部位置。如果系统开始变得更加内存紧张,你的进程是有可能被杀死的。

  • TRIM_MEMORY_COMPLETE:系统正运行与低内存的状态并且你的进程正处于LRU名单中最容易被杀掉的位置。你应该释放任何不影响你的app恢复状态的资源。

因为onTrimMemory()的回调是在API 14才被加进来的,对于老的版本,你可以使用onLowMemory()回调来进行兼容。onLowMemory()相当于TRIM_MEMORY_COMPLETE

Note: 当系统开始清除LRU缓存中的进程时,尽管它首先按照LRU的顺序来操作,但是它同样会考虑进程的内存使用量。因此消耗越少的进程则越容易被留下来。

参考链接:
1. 彻底理解android中的内部存储与外部存储
2. Android Training - 管理应用的内存
3. Android存储访问及目录
4. 【android】getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()的作用
5. Android进程的内存管理分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值