我苹果手机苹果内存不够怎么办,希望有能够专门存储图片并可以直接在上面看图片的设备

比特客户端
您的位置:
详解大数据
详解大数据
详解大数据
详解大数据
史上最全手机照片存储秘籍
关键字:QQ空间
  今年的端午节巧遇儿童节,来一场老少皆宜的亲子游是个不错的选择。如今拍照已经很普遍,不仅便携且能立刻上传到空间说说,朋友圈,等社交网络,但却有一个容量硬伤。大量的手机照片遇到内存不足问题怎么办?趁着假期还未来临,小编细心整理出了一份史上最全手机照片秘籍,以供有出行计划的朋友们参考。
  自助类
  随着长时间的使用,安装和卸载程序,系统垃圾会越来越多,内存也会缩小,别说存储旅游照片了,有时候连微信消息的图片都打不开。小编整理了两种方法,让大家可以自己动手轻松解决手机内存不足的问题。
  卸载应用:很多人有屯应用的习惯,甚至有些人手机中的软件有上百款,而常用的大概只有十多款。也就是说,有限的手机内存大都被不常用的应用占去了。是时候清理手机中不常用的应用了,安卓用户可以按照“设置--应用程序--管理应用程序--选择要卸载的应用程序--选择卸载”这五个步骤进行卸载;如果是手机,只需将手指按住某款应用的图标,直到所有图标开始抖动,然后按一下想删除的应用右上角的小叉就可以了。
  恢复出厂设置:这种方法适用于。首先进入手机的“设置”中,选择隐私权,再选择恢复出厂设置,点击重置手机即可。这种方法不能经常使用,因为恢复出厂设置后,手机上的一些个性化设置还有应用将会不能使用。强烈建议在恢复出厂设置之前将手机数据备份一下。
  硬件类
  :可随身携带的“”存储空间
  无线移动硬盘集成了电池和无线,只要你的无线终端设备通过与其相连,就能访问其中的数据,完全摆脱数据线的困扰。无线移动硬盘一般都拥有大容量的“私人云”存储空间,可以让智能手机、电脑捉襟见肘的容量问题完全得到解决。在旅途中,用手机和平板可以直接,甚至同时访问硬盘的内容,比如将iPhone等智能手机拍到的旅游照上传到硬盘的同时,可以用直接查看硬盘里的照片。
  OTG盘:兼顾移动存储、扩充容量和接口转接的功能
  将一根Micro USB转USB的连接线,设计成一个U盘大小,这就是OTG盘,可以完美解决旅行中不想带数据线的烦恼。有了这个,出门旅游就没必要携带读卡器或是,依然可以实现数据之间的转移。OTG盘还能为手机、平板等移动设备扩容,直接下载存储、数据备份等,相比网盘适用范围更广,比无线存储更便宜,比TF卡连接更方便,可谓优势多多。
  软件类
  微云:照片可供他人扫码下载
  微云提供一键相册备份功能,用户还可以设置微云在WiFi下后台每一张新拍的照片。微云支持无压缩上传照片原图,默认以时间轴进行显示,让照片的分类整理变得省时又省力。搭配微云所提供的免费10T空间,可以备份5000万张照片,相当于800部iPhone可以保存的照片。
  微云不仅可以把照片通过QQ好友、QQ群、微信、朋友圈、QQ空间、微博、邮箱等形式实现一键分享,更添加了面对面分享的绝妙途径。存储在微云上的照片,只需轻轻一点就能生成专属二维码。当拍到好照片想要与身边的人分享时,对方扫一扫即能下载。
  在安全防护方面,微云融合了帐号密码、独立密码与锁屏密码三重保护,可以说用户即使丢失了手机,也不用担心照片丢失的问题了,资源还都在云端拥有备份呢。
  云:“闪电互传”让不同平台之间的照片互传成为可能
  百度云最大容量为2T,虽不如微云的10T来得大气,但也足够使用。百度云支持照片按拍摄时间和拍摄地点查看,给后续的照片分类带来更多便捷。
  百度云的“闪电互传”功能能够进行跨平台传输,让、iOS两大平台之间的文件互传成为可能。并且,通过“闪电互传”功能,即使处在非WiFi的条件下,也可以将手机拍摄的照片高速分享给好友。
  QQ空间:相册容量可升级至无限量
  与微云和百度云不同,手机QQ空间并不是一款专门的存储应用,主打的是社交功能。不过,手机QQ空间相册在照片存储和分享方面也有不少亮点。在容量方面,QQ空间相册堪称土豪,最高相册容量可升级至无限量,真正的一辈子都用不完。新拍摄的照片在QQ空间相册中会以拍摄时间及地点为维度进行照片事件聚合展示,一定时间和距离范围内的照片会自动分组聚合,不再单纯依靠照片本身的时间信息平铺排列。
  QQ空间相册支持高清急速秒传,用户可以轻松保存原图。并且,用户只要将照片上传至相册,QQ空间就为其进行4重备份,如此一来,QQ空间相册就不仅仅是一个网络相册,而是云端照片库了。
  本文列举了三类能够解放手机内存的方法,愿能助力各位的旅行计划。最后,预祝大家假期愉快、一路顺风。
  (关注微信号:Qzoneplus,了解时下最热的旅游、亲子、美食、IT等资讯)
去年,手机江湖里的竞争格局还是…
甲骨文的云战略已经完成第一阶段…
软件信息化周刊
比特软件信息化周刊提供以数据库、操作系统和管理软件为重点的全面软件信息化产业热点、应用方案推荐、实用技巧分享等。以最新的软件资讯,最新的软件技巧,最新的软件与服务业内动态来为IT用户找到软捷径。
商务办公周刊
比特商务周刊是一个及行业资讯、深度分析、企业导购等为一体的综合性周刊。其中,与中国计量科学研究院合力打造的比特实验室可以为商业用户提供最权威的采购指南。是企业用户不可缺少的智选周刊!
比特网络周刊向企业网管员以及网络技术和产品使用者提供关于网络产业动态、技术热点、组网、建网、网络管理、网络运维等最新技术和实用技巧,帮助网管答疑解惑,成为网管好帮手。
服务器周刊
比特服务器周刊作为比特网的重点频道之一,主要关注x86服务器,RISC架构服务器以及高性能计算机行业的产品及发展动态。通过最独到的编辑观点和业界动态分析,让您第一时间了解服务器行业的趋势。
比特存储周刊长期以来,为读者提供企业存储领域高质量的原创内容,及时、全面的资讯、技术、方案以及案例文章,力求成为业界领先的存储媒体。比特存储周刊始终致力于用户的企业信息化建设、存储业务、数据保护与容灾构建以及数据管理部署等方面服务。
比特安全周刊通过专业的信息安全内容建设,为企业级用户打造最具商业价值的信息沟通平台,并为安全厂商提供多层面、多维度的媒体宣传手段。与其他同类网站信息安全内容相比,比特安全周刊运作模式更加独立,对信息安全界的动态新闻更新更快。
新闻中心热点推荐
新闻中心以独特视角精选一周内最具影响力的行业重大事件或圈内精彩故事,为企业级用户打造重点突出,可读性强,商业价值高的信息共享平台;同时为互联网、IT业界及通信厂商提供一条精准快捷,渗透力强,覆盖面广的媒体传播途径。
云计算周刊
比特云计算周刊关注云计算产业热点技术应用与趋势发展,全方位报道云计算领域最新动态。为用户与企业架设起沟通交流平台。包括IaaS、PaaS、SaaS各种不同的服务类型以及相关的安全与管理内容介绍。
CIO俱乐部周刊
比特CIO俱乐部周刊以大量高端CIO沙龙或专题研讨会以及对明星CIO的深入采访为依托,汇聚中国500强CIO的集体智慧。旨为中国杰出的CIO提供一个良好的互融互通 、促进交流的平台,并持续提供丰富的资讯和服务,探讨信息化建设,推动中国信息化发展引领CIO未来职业发展。
IT专家新闻邮件长期以来,以定向、分众、整合的商业模式,为企业IT专业人士以及IT系统采购决策者提供高质量的原创内容,包括IT新闻、评论、专家答疑、技巧和白皮书。此外,IT专家网还为读者提供包括咨询、社区、论坛、线下会议、读者沙龙等多种服务。
X周刊是一份IT人的技术娱乐周刊,给用户实时传递I最新T资讯、IT段子、技术技巧、畅销书籍,同时用户还能参与我们推荐的互动游戏,给广大的IT技术人士忙碌工作之余带来轻松休闲一刻。
微信扫一扫
关注Chinabyte如何解决手机内照片太多、空间不够用的问题呢?简单一招即可搞定
作者:佚名
字体:[ ] 来源:互联网 时间:10-31 11:09:37
最近我的手机总是提示系统存储空间不足,我每天都清理手机垃圾,下载的电影、电视剧、图片等我都清理了,但是还是提示我手机系统存储空间不足,那么如何解决手机内照片太多、空间不够用的问题呢?下面小编就为大家介绍一种方法,一起来看看吧
随着智能手机摄像头参数的不断提高,手机拍照体验已经逐渐超越数码相机。因此在大多数时候一般用户都会选择使用手机来记录日常和出游过程中所看到的人、发生的事。不过现在手机摄像头动辄超过两千万像素,拍摄的照片体积也日益增大,但仍然有不少用户在使用16GB甚至更小空间的手机设备。大量的照片让本就贫乏的内存空间捉襟见肘,实际上我们手机的大部分容量都是被无数张照片所消耗的。
那么怎样才能解决手机内照片太多、空间不够用的问题呢?目前一些手机厂商也为我们找到了一些方法。比如苹果iOS设备均支持iCloud空间,用户可以将平时拍摄的照片上传至iCloud,为iPhone手机腾出宝贵的内存空间。
不过,iCloud默认的5GB空间对于照片太多的用户而言可谓是杯水车薪。虽然iCloud也可以通过付费的方式扩容,但iCloud在国内的访问速度并不算快,甚至时常有无法访问的情况发生,为这样的服务付费实在有些不划算。
另一方面,国内已经有不少类似苹果iCloud的移动数据云端存储解决方案。比如360网盘、百度网盘、腾讯微云等,均支持将手机内的照片保存在网盘中。不过这些网盘往往做的&大而全&,更加偏重于文件存储和分享,而忽视了个人手机相册备份垂直功能。再加上360网盘已经确定关闭,百度网盘也开始针对免费用户限速,所以这类网盘类应用的使用体验并不算完美。
因袭小编更青睐于一些面向特定领域的云存储应用,比如提到文档的在线编辑和保存,大家首先想到的就是网易云笔记。而在手机相册的云备份方面,时光相册就是一款值得尝试的应用。
使用时光相册的方法十分简单,Android/iOS手机用户可以访问网址:http://a.app.qq.com/o/simple.jsp?pkgname=tc.everphoto&ckey=CK3 或直接在应用市场及AppStore搜索&时光相册&下载时光相册APP。PC和Mac设备的用户则可以直接访问时光相册的官网:https://everphoto.cn/管理自己的照片。这里就为大家简单介绍一下时光相册手机版的一些基本功能。
时光相册同时支持iOS和Android系统,只需要微信或者QQ帐号就可以直接注册登陆,初始状态下就提供了20GB的空间,另外也可以通过完善个人信息、观看教程等方式获取更多的空间,通常情况下免费赠送的空间就足够日常使用了。
和大多数手机照片备份应用一样,WiFi下自动备份照片是时光相册最基本的功能。虽然也可以在3G/4G网络下备份照片,但考虑到一张照片的体积在10MB左右,所耗费的流量是比较恐怖的,因此不推荐大家开启这一功能。
通常在使用手机云盘类应用将照片备份到云端之后,用户为了腾出手机空间一般就会把本地的照片删除了事。这样虽然释放了内存空间,但当到了想要找回这些老照片的时候,就必须手动到云端把这些照片重新下载回来,不仅麻烦而且还有可能耗费不必要的流量。
而时光相册则提供了一个&优化手机空间&的功能,这一功能会在将手机内的照片原图上传到云端的同时,还会在手机内部留下一个高清的缩略图。比如一张分辨率为的1600万像素在经过优化之后,会保留一张像素较低,但是体积更小的高清图,大小是原图的1/25。这样一来用户在想要分享这些照片的时候不再需要重新到云端下载原图,只需要分享这些保存在手机内的高清照片即可。毕竟在微信朋友圈、QQ空间里分享的照片也是经过压缩的,没有必要特地使用体积较大的原图。
如果你想批量分享原图的话,也可以使用时光相册自带的&批量分享&或共享相册功能,将多张照片打包在一个相册中分享给微信或者QQ好友。
就体验而言,优化手机空间功能对于16GB及以下小内存空间的手机非常有用,比如你的手机里装了5GB的照片,优化之后可能只需要265MB的空间,即释放了手机空间,又不影响日常使用这些照片。
有时候我们一次会拍摄多张相似的照片,而这些照片并非是必要的,却占用了宝贵的内存空间。因此时光相册也提供了清理相似照片的功能,可以自动帮你删除重复的照片。应用会根据一定的算法来判断哪张照片值得保留,哪张重复的照片需要删除。用户也可以根据自己的喜好来决定需要删除的照片。这对于平时手一抖就能拍下多张相同照片的用户而言是一个不错的功能。
当手机中保存了太多的照片而显得杂乱不堪的时候,时光相册也能够自动识别每张照片所相对应的主题,并将其分门别类。比如&人物&、&事物&、&地点&等等。而在&事物&这样的大类中,还会细分成&夜景&、&道路&、&建筑&、&风景&、&美食&等小类,帮助你快速找到想要的照片。
音乐相册则可以将多张照片打包成幻灯片的模式,并支持加入背景音乐,还提供了多种不同风格的模版。制作好的音乐相册也可以分享到QQ或者微信朋友圈,比较适合家有小宝,或者好事将近的年轻用户。
值得一提的是,除了备份手机内的照片相册之外,时光相册还支持从第三方网盘迁移照片数据。比如只需要访问时光相册360云盘迁移助手(网址https://360.everphoto.cn),就可以一键将原360云盘中的照片迁移到时光相册中。
由于360云盘即将关闭,近期进行下载操作的用户数量众多,因此如果360云盘中照片数量太多的用户很难一次性将照片下载到本地备份。而时光相册的360云盘一键迁移功能会在云端持续进行,并在完成后通过QQ和手机短信的方式提醒,这对于有360云盘内照片迁移需求的用户是一个很有用的功能。
总体来看,时光相册云端备份的方式可以非常方便的让用户在iOS、Android、PC和Mac等设备上同时查阅、管理自己的照片。优化手机空间的特色功能则在将原始照片保存在云端的同时,也为了用户提供了继续在本地浏览、分享高清照片的解决方案,还十分贴心的加入了照片去重的功能。就一款专业的手机端照片管理应用而言,时光相册的表现值得点赞。
大家感兴趣的内容
12345678910
最近更新的内容苹果手机里内存不够用照片跟视频不想删掉该怎么办_百度知道
苹果手机里内存不够用照片跟视频不想删掉该怎么办
我有更好的答案
望采纳!!,由于iPhone是无法增加外部存储的,所以,没有办法,只有这一个方法!不想删掉的视频和照片可以备份发到电脑存储或者任何移动存储设备
采纳率:69%
把照片和视屏备份或者导出到电脑上就好了饿哦
删除应用或者保存照片后删除了
照片跟视频导入到电脑里啊。估计你照片视频很多吧。
其他1条回答
为您推荐:
其他类似问题
苹果手机的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。你的位置: >
> Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手
图片加载性能优化永远是领域中一个无法绕过的话题,经过数年的发展,涌现了很多成熟的图片加载开源库,比如Fresco、Picasso、UIL等等,使得图片加载不再是一个头疼的问题,并且大幅降低了OOM发生的概率。然而,在图片加载方面我们是否可以就此放松警惕了呢?
开源图片加载库能为我们解决绝大部分有关图片的问题,然而并不是所有!
首先,图片从来源上可以分成三大类:网络图片、手机图片、APK资源图片。网络图片和手机图片都在图片加载库功能的覆盖范围内,基本上不用开发者太操心,但是APK资源图片却不在此范围!
关于APK资源图片有3个特征:
1、资源图片基本都是在xml中引用 ,在Java中也是通过资源ID查找 。
2、资源图片一般不使用异步记载,不会出现loading图这些中间状态。
3、资源图片不会加载失败,如果失败了那么APP也挂掉了。
正是由于这3点特征,所以图片加载库实在鞭长莫及。那么就很容易出现一个问题:图片过大导致OOM!
很多APP为了追求酷炫的效果,热衷于设计绚丽全屏背景页面。既然是为了炫酷,考虑到用户体验,这些全屏背景图自然不能使用网络图片了,所以,这些图片都被放在apk包中作为资源文件直接引用。
使用这些资源图片的方式一般都是:
android:background="@drawable/xxx"
正常情况下,这样使用自然不会出现问题,但是如果APP内存紧张,很容易就出现OOM,尤其是5.0版本以下的手机,经常跑着跑着就Crash了,始作俑者就是这个。
为了解决这种问题,最常用的方式是找设计师压缩图片。而压缩图片有两种方式:缩小尺寸和降低质量。那么,这两种方式是否有效呢?
1、缩小尺寸: 压缩图片的宽度和高度。由于图片的内存占用与宽高成正比,这种方式确实有效,但是图片显示时会被拉伸导致变形,从而失却美感。
2、降低质量: 降低图片的色彩度,像素颜色密度。这其实是一个误区,很多人认为图片的存储占用空间小,图片的内存占用就会小,其实是错误的观点。这是方式并不会影响图片的内存占用,反而由于质量降低(下文具体分析),使得页面缺乏质感。必须记住:图片的内存占用与图片质量毫无干系!
为了寻求一个合理的解决方案,必须知彼知己。下面,我们来详细分析下资源图片的内存占用的情况!(后文所说的图片,除非特殊指明,否则都默认指APK资源图片)。
1、计算Bitmap的内存占用
我们以一张标准720p的全屏图片为例,宽高比为720×1280,对应的资源文件夹为drawable-xhdpi。同样,设备以标准720p的小米2S手机为例,density=320。
首先,android设备上图片都被处理成Bitmap对象。生成Bitmap有一个非常重要的参数Config,属性值有ALPHA_8、RGB_565、ARGB_4444、ARGB_8888四种。不同的属性值对应的图片每个像素点占用内存大小不同,ALPHA_8每个像素占用1byte,RGB_565和ARGB_4444占用2byte,ARGB_8888占用4byte,其中ARGB_4444在高版本中已经废弃。
那么,资源图片被decode成Bitmap的时候,Config参数值是哪个呢?来看几段代码。
Resources.java
private Drawable loadDrawableForCookie(TypedValue value, int id, Theme theme) {
final String file = value.string.toString();
if (file.endsWith(".xml")) {
final XmlResourceParser rp = loadXmlResourceParser(file, id, value.assetCookie, "drawable");
dr = Drawable.createFromXml(this, rp, theme);
rp.close();
final InputStream is = mAssets.openNonAsset(value.assetCookie, file, AssetManager.ACCESS_STREAMING);
dr = Drawable.createFromResourceStream(this, value, is, file, null);
is.close();
Drawable.java
public static Drawable createFromResourceStream(Resources res, TypedValue value,
InputStream is, String srcName, BitmapFactory.Options opts) {
if (opts == null) opts = new BitmapFactory.Options();
opts.inScreenDensity = res != null ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
BitmapFactory.java
public static class Options {
* Image are loaded with the {@link Bitmap.Config#ARGB_8888} config by default.
public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
从上面资源文件生成BitmapDrawable的代码可知,Bitmap.Config使用的是默认值ARGB_8888,即图像每个像素点占用内存4byte。
我们图片的尺寸是720×1280,也就是说像素点个数是720×,所有像素点占用内存=720x6400 byte=3.515625M,这个大小是图片不做任何处理时占用的内存大小。
另外,不管图片的内容是什么样子,体现在内存中的也仅仅是每个像素点对应的字节的值不同,大小是一样的,即一张720×1280的空白图和一张720×1280的彩色绚图占用内存大小是一致的。所以说想要降低占用内存,唯有减小宽高尺寸。
刚刚说过,计算出来的3.515625M大小是图片未作任何处理时的大小,但是系统在将图片处理成Drawable对象的时候是否未作处理呢?答案是:不!
BitmapFactory.java
public static Bitmap decodeResourceStream(Resources res, TypedValue value,
InputStream is, Rect pad, Options opts) {
if (opts == null) {
opts = new Options();
if (opts.inDensity == 0 && value != null) {
final int density = value.
if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
} else if (density != TypedValue.DENSITY_NONE) {
opts.inDensity =
if (opts.inTargetDensity == 0 && res != null) {
opts.inTargetDensity = res.getDisplayMetrics().densityD
return decodeStream(is, pad, opts);
代码中Options有两个非常重要的参数,inDensity和inTargetDensity,先来解释一下这俩参数的作用。
inDensity表示被设定的图像密度,决定这个值的是图片所放置的文件目录,比如drawable-hdpi、drawable-xhdpi等等,其对应的density如下表:
代码中opts.inDensity 被赋值为 value.density,也就是资源维度对应的密度值。如果图片放在drawable-hdpi下,inDensity=240,如果放在drawable-xhdpi下,inDensity=320。
inTargetDensity表示最终需要适配到的图片密度,这个值由手机设备来决定,上面代码中其值为DisplayMetrics的densityDpi,手机屏幕越高清这个值越大,而我们例子中720p的小米2S对应的densityDpi=320。
如果inDensity的值和inTargetDensity的值不相等,那么图片尺寸就被会缩放,缩放的比例为 inTargetDensity / inDensity。当然,宽高是需要同时等比缩放的,不然图片就变形了。
前面说过图片占用内存与图片的尺寸有关,如果被尺寸缩放了,内存大小就变了。前面未作任何缩放处理的720×1280图占用内存是3.515625M,假设放在drawable-ldpi目录下inDensity=120,设备inTargetDensity=320,那么最终的占用内存大小将是3.515625Mx(320/120)x(320/120)=25M。
一张图片占用25M大小,很恐怖的一个值,这种情况下,app估计直接挂了,如果放在drawable-hdpi下,占用就是6.25M,drawable-xhdpi下占用是3.515625M。由此可见,图片放置的目录一定要慎重。
最终我们得出一个公式:
资源图片内存大小 = 宽 x 高 x 4 x (设备密度 / 资源维度密度)x(设备密度 / 资源维度密度)
2、图像后门inPurgeable
前面说到,资源图片防止的目录不对会导致内存占用翻倍,但也不是放的密度维度越高越好,毕竟还是要做适配,不然小尺寸图片显示在高清大屏幕上就不好看了。而即使图片放对位置,占用内存大小也是相当惊人的,来个十张大图应用内存就蹭蹭上去了,冷不丁还来个OOM。
相信很多人都找到过解决方案:inPurgeable,代码网上一搜一大推:
public static Bitmap readBitmap(Context context, int resId) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPurgeable =
opt.inInputShareable =
InputStream is =context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is, null, opt);
那么,这段代码是否起效果呢?答案是肯定的,以前经常报OOM的现在都好了,而且用AS的内存监视器一看,加载图片时基本上不占内存。不管有没有其它问题,姑且把这个称之为图像后门吧。
下面,我们来看这个后门为什么能起效果!
BitmapFactory.java
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
if (is == null) {
Bitmap bm =
if (is instanceof AssetManager.AssetInputStream) {
bm = decodeStreamInternal(is, outPadding, opts);
private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) {
byte [] tempStorage =
if (opts != null) tempStorage = opts.inTempS
if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
return nativeDecodeStream(is, tempStorage, outPadding, opts);
private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
Rect padding, Options opts);
很明显,decodeStream这段代码最终调用的是native层的类库,我们追踪下去查看(下面以JellyBean源码为例)。
BitmapFactory.cpp
static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
jobject options, bool allowPurgeable, bool forcePurgeable = false,
bool applyScale = false, float scale = 1.0f) {
if (!isPurgeable) {
decoder-&setAllocator(&javaAllocator);
if (isPurgeable) {
decodeMode = SkImageDecoder::kDecodeBounds_M
if (isPurgeable) {
pr = installPixelRef(bitmap, stream, sampleSize, doDither);
pr = bitmap-&pixelRef();
static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
int sampleSize, bool ditherImage) {
SkImageRef*
// only use ashmem for large images, since mmaps come at a price
if (bitmap-&getSize() &= 32 * 1024) {
pr = new SkImageRef_ashmem(stream, bitmap-&config(), sampleSize);
pr = new SkImageRef_GlobalPool(stream, bitmap-&config(), sampleSize);
相关isPurgeable的代码就这么多,最终关于图片的decode逻辑都在installPixelRef中,有一段逻辑值得玩味。如果图片大小(占用内存)大于32×1024=32K,那么就使用Ashmem,否则就就放入一个引用池中。
这个做法也很容易理解,如果图片不大,直接放到native层内存中,读取方便且迅速。如果图片过大,放到native层内存也就不合理了,不然图片一多,native层内存很难管理。但是如果使用Ashmem匿名共享内存方式,写入到设备文件中,需要时再读取就能避免很大的内存消耗了,另外,这块内存是由Linux系统的内存管理来管理的,系统内存不足可以直接回收。而且,由于Ashmem跨进程的特性,同一张图片内存是可以跨进程共享的,这也是inInputShareable属性的由来。
关于Ashmem不明白的,可以参考老罗的博客:
由此可见,如果inPurgeable=true,图片所占用的内存就完全与Java Heap无关了,自然就不会有OOM这种烦恼了。
但是,万事有利有弊,一件事情的成功往往是用牺牲其它方面换来的。
前面说过,使用Resources获取图片Drawable的时候,会默认使用inDensity和inTargetDensity属性缩放图片来达到适配不同分辨率屏幕的目的。但是如果设置了inPurgeable=true来避免在Java Heap中分配内存,inDensity和inTargetDensity这两个属性就不能再使用了,否则即使inPurgeable=true,图片仍然会在Java Heap中分配内存。关于这一点,从以下代码中可以验证:
BitmapFactory.cpp
static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
jobject options, bool allowPurgeable, bool forcePurgeable = false,
bool applyScale = false, float scale = 1.0f) {
bool willScale = applyScale && scale != 1.0f;
bool isPurgeable = !willScale &&
(forcePurgeable || (allowPurgeable && optionsPurgeable(env, options)));
在doDecode方法中,isPurgeable会重新赋值,首决条件是图片不会缩放(willScale),其次才会判断Options中的isPurgeable属性。很明显,如果inDensity和inTargetDensity两个属性断定图片需要缩放,isPurgeable会被强制设定成false。这么做的原因很简单,Ashmem不可能维护多套不同尺寸的相同图片。
如果要解决这种适配问题,唯一的解决方案就是图片切成不同的尺寸,放到不同维度的drawable目录下。这样虽然不能做到精准适配,但是可以做到大体适配。原理就是,不同分辨率的屏幕decode相匹配密度维度目录下的对应尺寸图片。
说完适配的问题,你以为坑就到此结束了?其实不然,真正的大问题不是这个!
我们来看inPurgeable属性的一段官方注释:
While inPurgeable can help avoid big Dalvik heap allocations (from API level 11 onward), it sacrifices performance predictability since any image that the view system tries to draw may incur a decode delay which can lead to dropped frames。
意思就是:虽然inPurgeable能避免在Heap中分配一大段内存,但这个是以牺牲性能为代价的,如果图片要绘制到View上可能出现延时导致掉帧。
前面说过,inPurgeable=true的情况下,大图使用Ashmem共享内存存储图片,但是这部分内存存储的仅仅是解码前的图片数据,我们获取的Bitmap只是一个空包弹,不含任何像素信息。当图片需要渲染的时候,先要对一个个像素点进行解码,这个过程是比较耗时的,而偏偏又发生在UI线程中,必须等图像解码完成,UI线程才能继续渲染。如果图片像素点过多,计算量大,很容易就导致卡帧。最坑爹的是,Ashmem内存是由Linux系统统一管理的,如果系统内存紧张,这块儿图片内存很容易被回收,当图片再次被渲染时,Ashmem设备文件就需要重新映射内存再重新解码。
综上所诉,虽然inPurgeable既能导致适配问题,又可能导致性能问题,那么我们为什么还要使用呢?理由很简单:相对于出现OOM导致Crash,这两点牺牲仍然是值得的!
Facebook出品的大名鼎鼎的图片加载库Fresco中对图片的处理都使用了inPurgeable=true,代码如下 :
BitmapFactory.Options = new BitmapFactory.Options();
options.inPurgeable =
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);
虽然,Fresco和我们所说的资源图片干系并不大,但是很多思想还是值得我们借鉴。另外,关于inPurgeable的问题点以及Fresco为什么仍然继续使用这个属性,在其介绍文章中写得很详细,有兴趣可以去阅读下:
(需要翻墙)。
3、被堵上的后门你还在用?
很多时候,知其然而不知其所以然,很容易出问题,如果又不关注版本变化,就肯定会出问题,inPurgeable就是一个很典型的例子。
在5.0版本及以上,inPurgeable这个属性已经被标志为过时了!即使inPurgeable=true,也不会再使用Ashmem内存存放图片,而是直接放到了Java Heap中,简而言之就是inPurgeable属性被忽略了。
因为Android系统从5.0开始对Java Heap内存管理做了大幅的优化。和以往不同的是,对象不再统一管理和回收,而是在Java Heap中单独开辟了一块区域用来存放大型对象,比如Bitmap这种,同时这块内存区域的垃圾回收机制也是和其它区域完全分开的,这样就使得OOM的概率大幅降低,而且读取效率更高。所以,用Ashmem来存储图片就完全没有必要了,何况后者还会导致性能问题。
既然这样,我们就需要考虑继续使用inPurgeable方式处理资源图片是否合理了。
如果仔细阅读过Resources的源码,会发现对于Drawable对象有一套缓存机制,比如当一张图片被解码成BitmapDrawable对象后,会被存储到缓存中,下次再使用这张图片将优先从缓存中获取,既避免了图片重复decode的耗时,又做到了内存的复用,大体代码如下:
Resources.java
Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
// First, check whether we have a cached version of this drawable
// that was inflated against the specified theme.
if (!mPreloading) {
final Drawable cachedDrawable = caches.getInstance(key, theme);
if (cachedDrawable != null) {
return cachedD
// Next, check preloaded drawables. These may contain unresolved theme
// attributes.
final ConstantS
if (isColorDrawable) {
cs = sPreloadedColorDrawables.get(key);
cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
// If we were able to obtain a drawable, store it in the appropriate
// cache: preload, not themed, null theme, or theme-specific.
if (dr != null) {
dr.setChangingConfigurations(value.changingConfigurations);
cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
在inPurgeable后门被堵上之后,如果我们仍然通过BitmapFactory.decodeStream的方式获取资源图片的Bitmap,就会导致相同的图片重复decode,且多次在Java Heap中开辟内存。
同样的方式,原本在5.0以下可以节省Java Heap内存占用,在5.0及以上反而成了真正内存杀手!
所以在真正使用inPurgeable时是需要区分版本的,最简单的解决方案如下:
public static Drawable decodeLargeResourceImage(Resources resources, int resId) {
if (Build.VERSION.SDK_INT &= Build.VERSION_CODES.LOLLIPOP) {
drawable = resources.getDrawable(resId, null);
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPurgeable =
opt.inInputShareable =
InputStream is = resources.openRawResource(resId);
drawable = new BitmapDrawable(resources, BitmapFactory.decodeStream(is, null, opt));
} catch (OutOfMemoryError e) {
drawable =
之前看过一篇文章,阿里手机淘宝客户端对存到Ashmem的图片解码做了优化,在工作线程中对图片真正解码,从而避免在UI线程渲染图片时解码,同时锁住Ashmem内存,防止在系统内存紧张时回收出现二次解码。
再者,针对资源图片,目前出现了SVG矢量图代替常规PNG图片的解决方案,但也仅仅限于线条简易的Icon图。
对于图片处理这一块,需要学习和研究的方面太多,路漫漫其修远兮,吾将上下而求索!
转载请注明: &
与本文相关的文章

我要回帖

更多关于 手机内存不够 的文章

 

随机推荐