07.Android之多媒体问题

目录介绍

  • 7.0.0.1 加载bitmap图片的时候需要注意什么?为何bitmap容易造成OOM?如何计算Bitmap占用内存?
  • 7.0.0.2 如何理解recycle释放内存问题?图片加载到内存其实有两部分数据,这是为何?
  • 7.0.0.3 如何在不压缩图片的情况下加载高清大图?加载图的机制是什么,为何不会内存泄漏?
  • 7.0.0.7 LRU算法的原理?核心思想是什么?如果缓存满了的话,什么方法来管理移除最近最少使用的item和添加新的item?

好消息

  • 博客笔记大汇总【15年10月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计500篇[近100万字],将会陆续发表到网上,转载请注明出处,谢谢!
  • 链接地址:https://github.com/yangchong211/YCBlogs
  • 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!所有的笔记将会更新到GitHub上,同时保持更新,欢迎同行提出或者push不同的看法或者笔记!

7.0.0.1 加载bitmap图片的时候需要注意什么?为何bitmap容易造成OOM?如何计算Bitmap占用内存?

  • 注意问题
    • 直接加载大容量的高清Bitmap很容易出现显示不完整、内存溢出OOM的问题,所以最好按一定的采样率将图片缩小后再加载进来
    • 为减少流量消耗,可对图片采用内存缓存策略,又为了避免图片占用过多内存导致内存溢出,最好以软引用方式持有图片
    • 如果还需要网上下载图片,注意要开子线程去做下载的耗时操作技术博客大总结
  • 为何bitmap容易造成OOM
  • 如何计算Bitmap占用内存
    • 1.1 如何计算占用内存
      • 如果图片要显示下Android设备上,ImageView最终是要加载Bitmap对象的,就要考虑单个Bitmap对象的内存占用了,如何计算一张图片的加载到内存的占用呢?其实就是所有像素的内存占用总和:
      • bitmap内存大小 = 图片长度 x 图片宽度 x 单位像素占用的字节数
      • 起决定因素就是最后那个参数了,Bitmap'常见有2种编码方式:ARGB_8888和RGB_565,ARGB_8888每个像素点4个byte,RGB_565是2个byte,一般都采用ARGB_8888这种。那么常见的1080*1920的图片内存占用就是:1920 x 1080 x 4 = 7.9M
    • 1.2 上面方法计算内存对吗
      • 我看到好多博客都是这样计算的,但是这样算对吗?有没有哥们试验过这种方法正确性?我觉得看博客要对博主表示怀疑,论证别人写的是否正确。更多详细可以看我的GitHub:https://github.com/yangchong211
        • 说出我的结论:上面1.1这种说法也对,但是不全对,没有说明场景,同时也忽略了一个影响项:Density。接下来看看源代码。
        • inDensity默认为图片所在文件夹对应的密度;inTargetDensity为当前系统密度。
        • 加载一张本地资源图片,那么它占用的内存 = width * height * nTargetDensity/inDensity * nTargetDensity/inDensity * 一个像素所占的内存。
        @Nullable
        public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
                @Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
            validate(opts);
            if (opts == null) {
                opts = new Options();
            }
        
            if (opts.inDensity == 0 && value != null) {
                final int density = value.density;
                if (density == TypedValue.DENSITY_DEFAULT) {
                    opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
                } else if (density != TypedValue.DENSITY_NONE) {
                    opts.inDensity = density;
                }
            }
            
            if (opts.inTargetDensity == 0 && res != null) {
                opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
            }
            
            return decodeStream(is, pad, opts);
        }
        
      • 正确说法,这个注意呢?计算公式如下所示
        • 对资源文件:width * height * nTargetDensity/inDensity * nTargetDensity/inDensity * 一个像素所占的内存;
        • 别的:width * height * 一个像素所占的内存;
    • 1.3 一个像素占用多大内存技术博客大总结
      • Bitmap.Config用来描述图片的像素是怎么被存储的?
        • ARGB_8888: 每个像素4字节. 共32位,默认设置。
        • Alpha_8: 只保存透明度,共8位,1字节。
        • ARGB_4444: 共16位,2字节。
        • RGB_565:共16位,2字节,只存储RGB值。

7.0.0.2 如何理解recycle释放内存问题?图片加载到内存其实有两部分数据,这是为何?

  • 如何理解recycle释放内存问题?
    • 在Android2.3.3(API 10)及之前的版本中,Bitmap对象与其像素数据是分开存储的,Bitmap对象存储在Dalvik heap中,而Bitmap对象的像素数据则存储在Native Memory(本地内存)中或者说Derict Memory(直接内存)中,这使得存储在Native Memory中的像素数据的释放是不可预知的,我们可以调用recycle()方法来对Native Memory中的像素数据进行释放,前提是你可以清楚的确定Bitmap已不再使用了,如果你调用了Bitmap对象recycle()之后再将Bitmap绘制出来,就会出现”Canvas: trying to use a recycled bitmap”错误,而在Android3.0(API 11)之后,Bitmap的像素数据和Bitmap对象一起存储在Dalvik heap中。
  • 图片加载到内存其实有两部分数据,这是为何?技术博客大总结
    • 一个图片加载到内存里,其实是有两部分数据组成,一部分是图片的相关描述信息,另一部分就是最重要的像素信息(这部分是有byte数组组成的),android系统为了提高对图片的处理效率,对于图片的处理都是调用了底层的功能(由C语言实现的),也就是说一个图片加载到内存里后是使用两部分的内存区域,简单的说:一部分是java可用的内存区,一部分是c可用的内存区,这两个内存区域是不能相互直接使用的,这个bitmap对象是由java分配的,当然不用的时候系统会自动回收了,可是那个对应的C可用的内存区域jvm是不能直接回收的,这个只能调用底层的功能释放。所以你要调用recycle方法来释放那一部分内存。
  • 查看源码如下所示
    • image
    • 翻译这段解释:释放bitmap内存的时候,它会释放和这个bitmap有关的native内存,同时它会清理有关数据对象的引用,但是这里处理数据对象的引用,并不是立即清理数据(他并不是调用玩recycle()方法,就直接清理这个内存,他只是给垃圾回收机制发送一个指令,让它在bitmap没有对象引用的时候,来进行垃圾回收)。当调用recycle()方法之后,这个bitmap就会被表明为“死亡状态”。这个时候你在调用bitmap其他相关的方法,例如果get像素()或set像素()就会抛出一个异常。同时这个操作是不可逆的,所以一定百分之百确定这个bitmap在以后的场景下,不会被你的程序在使用到,再去调用recycle()方法。所以谷歌源码中建议我们,可以不用去主动调用recycle()方法,因为在没有引用的情况下,我们的垃圾回收机制会主动的清理内存。
    • 通过看源码,我们会发现,这个方法首先将这个Bitmap的引用置为null,然后调用了nativeRecycle(mNativeBitMap)方法,这个方法很明显是个JNI调用,会调用底层的c或者c++代码就可以做到对该内存的立即回收,而不需要等待那不确定啥时候会执行的GC来回收了。

7.0.0.3 如何在不压缩图片的情况下加载高清大图?加载图的机制是什么,为何不会内存泄漏?

  • 如何在不压缩图片的情况下加载高清大图?
    • 使用BitmapRegionDecoder,主要用于显示图片的某一块矩形区域,如果你需要显示某个图片的指定区域,那么这个类非常合适。
  • 加载图的机制是什么,为何不会内存泄漏?
  • 自定义可拖动的显示高清大图的View技术博客大总结
    • 提供一个设置图片的入口,setInputStream里面去获得图片的真实的宽度和高度,以及初始化我们的mDecoder
    • 重写onTouchEvent,在里面根据用户移动的手势,去更新显示区域的参数。在onMeasure里面为我们的显示区域的rect赋值,大小为view的尺寸
    • 每次更新区域参数后,调用invalidate,onDraw里面去regionDecoder.decodeRegion拿到bitmap,然后draw。

7.0.0.7 LRU算法的原理?核心思想是什么,谈谈你的思路?

  • 为减少流量消耗,可采用缓存策略。常用的缓存算法是LRU(Least Recently Used):
    • 核心思想:当缓存满时, 会优先淘汰那些近期最少使用的缓存对象。主要是两种方式:
      • LruCache(内存缓存):LruCache类是一个线程安全的泛型类:内部采用一个LinkedHashMap以强引用的方式存储外界的缓存对象,并提供get和put方法来完成缓存的获取和添加操作,当缓存满时会移除较早使用的缓存对象,再添加新的缓存对象。
      • DiskLruCache(磁盘缓存): 通过将缓存对象写入文件系统从而实现缓存效果
  • 大概过程如下?技术博客大总结
    • LruCache是android提供的一个缓存工具类,其算法是最近最少使用算法。它把最近使用的对象用“强引用”存储在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预设定值之前就从内存中移除。
  • 如果缓存满了的话,什么方法来管理移除最近最少使用的item和添加新的item?
    • trimToSize()方法,删除最年长的条目,直到剩余条目的总数达到或低于请求的大小
      public void trimToSize(int maxSize) {
          while(true) {
              Object key;
              Object value;
              synchronized(this) {
                  if (this.size < 0 || this.map.isEmpty() && this.size != 0) {
                      throw new IllegalStateException(this.getClass().getName() + ".sizeOf() is reporting inconsistent results!");
                  }
      
                  if (this.size <= maxSize || this.map.isEmpty()) {
                      return;
                  }
      
                  Entry<K, V> toEvict = (Entry)this.map.entrySet().iterator().next();
                  key = toEvict.getKey();
                  value = toEvict.getValue();
                  this.map.remove(key);
                  //计算现在缓存的大小,然后减掉多余的,内部调用的是sizeOf()方法
                  this.size -= this.safeSizeOf(key, value);
                  ++this.evictionCount;
              }
      
              //如果你想在在我们的缓存中实现二级缓存,可以实现此方法,源码中是空方法。
              this.entryRemoved(true, key, value, (Object)null);
          }
      }
      

关于其他内容介绍

01.关于博客汇总链接

02.关于我的博客

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 目录介绍 01.如何计算Bitmap占用内存1.1 如何计算占用内存1.2 上面方法计算内存对吗1.3 一个像素占...
    杨充211阅读 3,864评论 1 9
  • 2021期待与你一起共事,点击查看岗位[https://www.jianshu.com/p/6f4d67fa406...
    闲庭阅读 16,510评论 0 75
  • 7.1 压缩图片 一、基础知识 1、图片的格式 jpg:最常见的图片格式。色彩还原度比较好,可以支持适当压缩后保持...
    AndroidMaster阅读 2,430评论 0 13
  • 在这样一个丧心病狂的社群里:有这样一个人,会第一时间导出语音,及时更新网盘;有这样一个人,会用导图整理当日课程分享...
    Miss伊柚阅读 255评论 0 0
  • “叶君好!你眼里到底有没有我这个爸爸!”叶父听见叶君好的话,又扔了筷子,瞪眼。“很明显,你认为没有。”叶君好没停筷...
    是叶闲鱼1号啊阅读 316评论 3 1