77百科网
当前位置: 首页 生活百科

androidglide加载不出(Android性能优化Glide巨图加载原理分析)

时间:2023-06-09 作者: 小编 阅读量: 1 栏目名: 生活百科

简介Glide是目前非常流行的图片加载第三方开源库,而且功能极其强大,内部代码复杂程度也极其大。Glide是纯Java写的Android端开源图片加载库,能够帮助我们下载、缓存、展示多种格式图片,也包括GIF格式。所以Glide尽量的复用资源来防止不必要的GC_FOR_ALLOC引起卡顿。RequestManager用来跟踪众多当前页面的Request的是RequestTracker类,用弱引用来保存运行中的Request,用强引用来保存暂停需要恢复的Request。

简介

Glide 是目前非常流行的图片加载第三方开源库,而且功能极其强大,内部代码复杂程度也极其大。

Glide是纯Java写的Android端开源图片加载库,能够帮助我们下载、缓存、展示多种格式图片,也包括GIF格式 。

特点:
  • (1)使用简单
  • (2)可配置度高,自适应程度高
  • (3)支持常见图片格式 Jpg png gif webp
  • (4)支持多种数据源 网络、本地、资源、Assets 等
  • (5)高效缓存策略 支持Memory和Disk图片缓存 默认Bitmap格式采用RGB_565内存使用至少减少一半
  • (6)生命周期集成 根据Activity/Fragment生命周期自动管理请求
  • (7)高效处理Bitmap 使用Bitmap Pool使Bitmap复用,主动调用recycle回收需要回收的Bitmap,减小系统回收压力
原理Glide库的资源复用:
  • Android的内存申请几乎都在new的时候发生,而new较大对象(比如Bitmap时),更加容易触发GC_FOR_ALLOW。所以Glide尽量的复用资源来防止不必要的GC_FOR_ALLOC引起卡顿。
  • 最显著的内存复用就是内存LruResourceCache(第一次从网络或者磁盘上读取到Resource时,并不会保存到LruCache当中,当Resource被release时,也就是View不在需要此Resource时,才会进入LruCache当中)
  • 还有BitmapPool(Glide会尽量用图片池来获取到可以复用的图片,获取不到才会new,而当LruCache触发Evicted时会把从LruCache中淘汰下来的Bitmap回收,也会把transform时用到的中间Bitmap加以复用及回收)
Glide库图片池:
  • 4.4以前是Bitmap复用必须长宽相等才可以复用
  • 4.4及以后是Size>=所需就可以复用,只不过需要调用reconfigure来调整尺寸
  • Glide用AttributeStategy和SizeStrategy来实现两种策略
  • 图片池在收到传来的Bitmap之后,通过长宽或者Size来从KeyPool中获取Key(对象复用到了极致,连Key都用到了Pool),然后再每个Key对应一个双向链表结构来存储。每个Key下可能有很多个待用Bitmap
  • 取出后要减少图片池中记录的当前Size等,并对Bitmap进行eraseColor(Color.TRANSPAENT)操作确保可用
Glide加载发起流程:
  1. Glide.with(context)创建RequestManager
  • RequestManager负责管理当前context的所有Request
  • Context可以传Fragment、Activity或者其他Context,当传Fragment、Activity时,当前页面对应的Activity的生命周期可以被RequestManager监控到,从而可以控制Request的pause、resume、clear。这其中采用的监控方法就是在当前activity中添加一个没有view的fragment,这样在activity发生onStart onStop onDestroy的时候,会触发此fragment的onStart onStop onDestroy。
  • RequestManager用来跟踪众多当前页面的Request的是RequestTracker类,用弱引用来保存运行中的Request,用强引用来保存暂停需要恢复的Request。

2.Glide.with(context).load(url)创建需要的Request

  • 通常是DrawableTypeRequest,后面可以添加transform、fitCenter、animate、placeholder、error、override、skipMemoryCache、signature等等
  • 如果需要进行Resource的转化比如转化为Byte数组等需要,可以加asBitmap来更改为BitmapTypeRequest
  • Request是Glide加载图片的执行单位

3.Glide.with(context).load(url).into(imageview)

  • 在Request的into方法中会调用Request的begin方法开始执行
  • 在正式生成EngineJob放入Engine中执行之前,如果并没有事先调用override(width, height)来指定所需要宽高,Glide则会尝试去获取imageview的宽和高,如果当前imageview并没有初始化完毕取不到高宽,Glide会通过view的ViewTreeObserver来等View初始化完毕之后再获取宽高再进行下一步
Glide加载资源:
  • GlideBuilder在初始化Glide时,会生成一个执行机Engine
  • Engine中包含LruCache缓存及一个当前正在使用的active资源Cache(弱引用)
  • activeCache辅助LruCache,当Resource从LruCache中取出使用时,会从LruCache中remove并进入activeCache当中
  • Cache优先级LruCache>activeCache
  • Engine在初始化时要传入两个ExecutorService,即会有两个线程池,一个用来从DiskCache获取resource,另一个用来从Source中获取(通常是下载)
  • 线程的封装单位是EngineJob,有两个顺序状态,先是CacheState,在此状态先进入DiskCacheService中执行获取,如果没找到则进入SourceState,进到SourceService中执行下载
Glide常用的加载方法1、加载图片到imageView

1. Glide.with(Context context).load(Strint url).into(ImageView imageView);

2、各种形式的图片加载到ImageView

1. // 加载本地图片 2. File file = new File(getExternalCacheDir()"/image.jpg"); 3. Glide.with(this).load(file).into(imageView); 4. // 加载应用资源 5. int resource = R.drawable.image; 6. Glide.with(this).load(resource).into(imageView); 7. // 加载二进制流 8. byte[] image = getImageBytes(); 9. Glide.with(this).load(image).into(imageView); 10. // 加载Uri对象 11. Uri imageUri = getImageUri(); 12. Glide.with(this).load(imageUri).into(imageView);

3、加载带有占位图

1. Glide.with(this).load(url).placeholder(R.drawable.loading).into(imageView);

占位图目的为在目的图片还未加载出来的时候,提前展示给用户的一张图片;

4、加载失败 放置占位符

1. Glide.with(this).load(url).placeholder(R.drawable.loading).error(R.drawable.error) 2..diskCacheStrategy(DiskCacheStrategy.NONE)//关闭Glide的硬盘缓存机制 3..into(imageView); 4. //DiskCacheStrategy.NONE:表示不缓存任何内容。 5. //DiskCacheStrategy.SOURCE:表示只缓存原始图片。 6. //DiskCacheStrategy.RESULT:表示只缓存转换过后的图片(默认选项)。 7. //DiskCacheStrategy.ALL :表示既缓存原始图片,也缓存转换过后的图片。

5、加载指定格式的图片--指定为静止图片

1. Glide.with(this) 2..load(url) 3..asBitmap()//只加载静态图片,如果是git图片则只加载第一帧。 4..placeholder(R.drawable.loading) 5..error(R.drawable.error) 6..diskCacheStrategy(DiskCacheStrategy.NONE) 7..into(imageView);

6、加载动态图片

1. Glide.with(this) 2..load(url) 3..asGif()//加载动态图片,若现有图片为非gif图片,则直接加载错误占位图。 4..placeholder(R.drawable.loading) 5..error(R.drawable.error) 6..diskCacheStrategy(DiskCacheStrategy.NONE) 7..into(imageView);

7、加载指定大小的图片

1. Glide.with(this) 2..load(url) 3..placeholder(R.drawable.loading) 4..error(R.drawable.error) 5..diskCacheStrategy(DiskCacheStrategy.NONE) 6..override(100, 100)//指定图片大小 7..into(imageView);

8、关闭框架的内存缓存机制

1. Glide.with(this) 2..load(url) 3..skipMemoryCache(true) //传入参数为false时,则关闭内存缓存。 4..into(imageView);

9、关闭硬盘的缓存

1. Glide.with(this) 2..load(url) 3..diskCacheStrategy(DiskCacheStrategy.NONE)//关闭硬盘缓存操作 4..into(imageView); 5. //其他参数表示: 6. //DiskCacheStrategy.NONE:表示不缓存任何内容。 7. //DiskCacheStrategy.SOURCE:表示只缓存原始图片。 8. //DiskCacheStrategy.RESULT:表示只缓存转换过后的图片(默认选项)。 9. //DiskCacheStrategy.ALL :表示既缓存原始图片,也缓存转换过后的图片。

10、当引用的 url 存在 token 时解决方法

1. public class MyGlideUrl extends GlideUrl { 2.private String mUrl; 3.public MyGlideUrl(String url) { 4. •super(url); 5. •mUrl = url; 6.} 7.@Override 8.public String getCacheKey() { 9. •return mUrl.replace(findTokenParam(), ""); 10.} 11.private String findTokenParam() { 12. •String tokenParam = ""; 13. •int tokenKeyIndex = mUrl.indexOf("?token=") >= 0 ? mUrl.indexOf("?token=") : mUrl.indexOf("&token="); 14. •if (tokenKeyIndex != -1) { 15. •int nextAndIndex = mUrl.indexOf("&", tokenKeyIndex1); 16. •if (nextAndIndex != -1) { 17. •tokenParam = mUrl.substring(tokenKeyIndex1, nextAndIndex1); 18. •} else { 19. •tokenParam = mUrl.substring(tokenKeyIndex); 20. •} 21. •} 22. •return tokenParam; 23.} 24. }

然后加载图片的方式为:

1. Glide.with(this) 2..load(new MyGlideUrl(url)) 3..into(imageView);

11、利用Glide将图片加载到不同控件或加载成不同使用方式

(1)、拿到图片实例

1. //1、通过自己构造 target 可以获取到图片实例 2. SimpleTarget<GlideDrawable> simpleTarget = new SimpleTarget<GlideDrawable>() { 3.@Override 4.public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) { 5. •imageView.setImageDrawable(resource); 6.} 7. }; 8. //2、将图片实例记载到指定的imageview上,也可以做其他的事情 9. public void loadImage(View view) { 10.String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg"; 11.Glide.with(this) 12. •.load(url) 13. •.into(simpleTarget); 14. }

(2)、将图片加载到任何位置

1. /* 2. *将图片加载为控件背景 3. */ 4. public class MyLayout extends LinearLayout { 5.private ViewTarget<MyLayout, GlideDrawable> viewTarget; 6.public MyLayout(Context context, AttributeSet attrs) { 7. •super(context, attrs); 8. •viewTarget = new ViewTarget<MyLayout, GlideDrawable>(this) { 9. •@Override 10. •public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) { 11. •MyLayout myLayout = getView(); 12. •myLayout.setImageAsBackground(resource); 13. •} 14. •}; 15.} 16.public ViewTarget<MyLayout, GlideDrawable> getTarget() { 17. •return viewTarget; 18.} 19.public void setImageAsBackground(GlideDrawable resource) { 20. •setBackground(resource); 21.} 22. } 23. //引用图片到指定控件作为背景 24. public class MainActivity extends AppCompatActivity { 25.MyLayout myLayout; 26.@Override 27.protected void onCreate(Bundle savedInstanceState) { 28. •super.onCreate(savedInstanceState); 29. •setContentView(R.layout.activity_main); 30. •myLayout = (MyLayout) findViewById(R.id.background); 31.} 32.public void loadImage(View view) { 33. •String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg"; 34. •Glide.with(this) 35. •.load(url) 36. •.into(myLayout.getTarget()); 37.} 38. }

12、Glide 实现预加载

1. //a、预加载代码 2. Glide.with(this) 3..load(url) 4..diskCacheStrategy(DiskCacheStrategy.SOURCE) 5..preload(); 6. //preload() 有两种重载 7.// 1、带有参数的重载,参数作用是设置预加载的图片大小; 8. //2、不带参数的表示加载的图片为原始尺寸; 9. //b、使用预加载的图片 10. Glide.with(this) 11..load(url) 12..diskCacheStrategy(DiskCacheStrategy.SOURCE) 13..into(imageView);

总结流程图

Glide 是目前非常流行的图片加载第三方开源库,而且功能极其强大,内部代码复杂程度也极其大。经过一番心理斗争决定还是要好好学习Glide的部分源码设计。关于更多 Glide学习,我这里推荐网易高级攻城狮整理的《铺路架构师学习手册》,里面内容(100w字图解析 实战笔记)。加油Android人,不学永远在一个阶梯。私信:“手册”获取哦!

【私信:“手册”领取】大厂架构深度讲解手册

    推荐阅读
  • 深度还原20年前游戏厅(游戏厅最真实的众生相)

    深处底层,稍微沾染了一些社会风气就觉得自己了不起了,流里流气,抽烟戴墨镜,渐渐形成了一些“帮派”。)“讲义气”、“耿直人”的确是那个时代人们眼中好的品性,但真正因电影而误入歧途的人不是很多,毕竟帮派的存在已经不知道几百年历史了。帮派之间的群殴,经常发生,偶尔也会发生大事,闹得沸沸扬扬。

  • 重庆创新经济走廊开发建设(众多专家齐聚高峰论坛纵论提质发展)

    陈浩杰认为,当前,融合发展已成为中国夜间经济创新发展的一大趋势。从消费领域来看,重庆夜间经济发展则存在不平衡的现象。今年7月22日晚,“2021不夜重庆生活节”如期而至。在未来3个月,主办方将组织开展近200场融合消费促进、商旅文体元素的夜间特色主题活动,唱响“不夜重庆”品牌。而在此前不久,重庆夜间经济发展联合会宣告成立。市商务委相关负责人表示,发展夜间经济,是重庆建设国际消费中心城市的重点内容。

  • 薄荷好养吗,怎么养才能没虫子,在家如何种植薄荷

    注意千万不要倒太多了,否则也是浪费。薄荷对土壤要求不严,但肥沃、疏松透气的沙质土壤或者半沙质土壤最为适宜种植薄荷。薄荷适合半阴环境下种植即散光照射,夏日光照强烈,需要做一定的遮光处理。薄荷具有醒脑、兴奋的作用,所以适量的食用一些薄荷,可以起到清心宁神,还可以恢复精神,是消除疲劳的提神剂,但是在晚上不适合食用,也不适合过量食用。

  • 魔兽世界怀旧服tbc战士有几种形态(魔兽世界怀旧服)

    魔兽世界怀旧服tbc战士有几种形态作者:NGA-thedeadman此文仅针对当前P1阶段的各种基础问题。对于各项数据的讨论不做展开,也不涉及后续阶段内容,只基於往年TBC经验作出参考性建议。装备基本合格以后,堆满免爆防等490,其余属性根据自己的团队构架和自身实际装备情况选择。毁灭打击固有仇恨:10515X破甲层数,满破前应加上破甲的301仇恨。95%以上的情况,我们应该使用快速武器。

  • 美国黄石公园今年要喷发吗(美国黄石国家公园因洪水关闭)

    美国国家公园管理局及美国媒体发布的画面显示,13日,黄石国家公园北半部及附近地区的山体滑坡严重破坏了当地道路,部分桥梁被大水损毁,小型房屋甚至被洪水整体冲走。美国国家公园管理局当日在其官网上说,黄石国家公园的5个入口全部关闭。目前,公园内剩下的十几名露营游客正在撤离中。据公园统计,2021年全年共有超过400万人次游客来访。2020年,该公园因新冠疫情关闭近两个月。黄石国家公园官员认为,该公园因洪水关闭尚属首次。

  • 胃胀气怎么快速排气7个小妙招(吃什么顺气最快)

    大家好,今天呢,想要和大家说的是出现胃胀气,吃什么顺气最快?对于出现胃部不适,一定要明确造成腹胀或者胃气上逆的原因,这样,再选择合适的食物或药物顺气效果会更好。在中医上,胃气以降为顺~如果胃气停聚中焦甚至上逆,出现恶心、呃逆的症状,应当多吃顺气的食物。比如,白萝卜就具有很好的降气止逆功效,把白萝卜切成丁状,煮水喝,可以很好地顺气。关注我,了解更多医学科普小知识。

  • 摆摊卖苹果技巧(快速卖苹果的几种方式)

    每个乡村镇上都会有集,果农可以带上一些苹果在集上卖,虽然集上卖出的价格不会太高,数量也不会太多,但是聊胜于无,可以让我们多卖出一些苹果。菜市场上卖苹果。而且如果苹果好吃的话,会经常光顾,成为你的回头客的。自己找超市、水果店、幼儿园、公司等去咨询是否有采购苹果的计划。

  • 元宵节诗词(元宵节盘点)

    月上柳梢头,人约黄昏后____欧阳修《生查子·元夕》,今天小编就来聊一聊关于元宵节诗词?____欧阳修《生查子·元夕》去年元夜时,花市灯如昼。____欧阳修《生查子·元夕》谁教岁岁红莲夜,两处沉吟各自知。____姜夔《鹧鸪天·元夕有所梦》火树银花合,星桥铁锁开。____辛弃疾《青玉案·元夕》凤箫声动,玉壶光转,一夜鱼龙舞。____辛弃疾《青玉案·元夕》千门开锁万灯明,正月中旬动地京。____张祜《正月十五夜灯》今年元夜时,月与灯依旧。

  • 1.8排量车船税多少(1.8t排量的车船税收多少)

    2012年新的车船税将按7个档次征收1.0升(含)以下60元至360元1.0升以上至1.6升(含)300元至540元1.6升以上至2.0升(含)360元至660元2.0升以上至2.5升(含)660元至1200元2.5升以上至3.0升(含)1200元至2400元3.0升以上至4.0升(含)2400元至3600元4.0升以上3600元至5400元凡发动机排气量小于或者等于l升的载客汽车,都应按照微型客车的税额标准征收车船税。发动机排气量以如下凭证相应项目所载数额为准。

  • 打游戏手出汗怎么解决影响操作怎么办(怎么解决)

    跟着小编一起来看一看吧!打游戏手出汗怎么解决影响操作怎么办爽身粉。爽身粉中含有止汗成分,可以让你打游戏时出汗手掌保持比较干燥。走珠是小编用的最多的也是最有效的,因为走珠本来就是用来抑制腋下出汗带来的异味,所以用来抑制手出汗也没有什么问题。香皂是我们最常见的家庭生活用品,香皂用来洗手后,会让手掌长时间保持干燥。洗完手你打游戏感觉都不一样啦。