Android Fresco (Facebook开源的图片加载管理库)

时间:2023-01-08 15:21:53

Fresco是Facebook开源的一个图片加载和管理库.

这里是Fresco的GitHub网址.

同类型的开源库市面有非常多,比如Picasso, Universal Image Loader, Glide, Volley.

而Fresco的最大特点在于,图片不在Java Heap上分配内存!

对,你没看错,困扰许多开发很久的爆Java Heap抛出OutOfMemoryError的无解难题看到了曙光!

那到底Fresco都把图片存到内存的那一片区域了呢?

答案是:Ashmem,匿名共享内存. 关于Ashmem的介绍,推荐看Android大牛罗升阳的这3篇技术Blog.

1. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划

2. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

3. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析

Ashmem:

在Android系统里面,Ashmem这个区域的内存并不属于Java Heap,也不属于Native Heap.而Ashmem的使用,又有一点像Java的垃圾回收.

当Ashmem中的某个内存空间像要被释放时候,会通过系统调用unpin来告知.但实际上这块内存空间的数据并没有被真正的擦除.

如果Android系统发现内存吃紧时,就会把unpin的内存空间利用起来去存储所需的数据.

而被unpin的内存空间,是可以被重新pin的,如果此时的该内存空间还没有被其他人使用的话,就节省了重新往Ashmem重新写入数据的过程了.

所以,Ashmem这个工作原理是一种延迟释放.

Bitmap在Ashmem中的使用

Ashmem内存区域是不能被Java应用直接使用的,但这其中有一些例外,而Bitmap是其中一个.

BitmapFactory.Options = new BitmapFactory.Options();
options.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);

Purgeable被设置成true以后,这个Bigmap就是保存在Ashmem内存区域中的,Java的垃圾回收是不能回收这篇区域的内存的.

当Android系统需要渲染这个Bitmap的时候,会调用pin,渲染完成后会调用unpin.而unpin后的内存空间表示能被其他人所使用.

如果被unpin的Bitmap需要重新渲染,系统会再次Decode这个Bitmap.而这个Decode的过程是在UI线程上完成的.所以Google后来废弃了这个pureable的参数.

后来Google提供了另外一个Flag,叫inBitmap.很遗憾的是,知道Android4.4后,这个新的Flag才得到完善.而Fresco致力于实现一个包括Android2.3以及以上的Android系统都能完美工作的图片加载管理开源库,因此Fresco放弃了使用inBitmap的解决方案.

Fresco是如何利用Ashmem去给Bitmap分配和管理内存?

上面说到的pin和unpin两个操作,对应的NDK调用是AndroidBitmap_lockPixels和unlockPixels.按照我们一惯认知,为了避免内存泄漏,这两者必须成对出现.而Fresco为了避免Bitmap再次渲染而导致的在UI线程Decode的过程,偏偏不在渲染完成后调用unlockPixels.

这做后,Fresco需要自己去管理这块内存区域,保证当这个Bitmap不再使用时,Ashmem的内存空间能被unpin.

而Fresco选择在Bitmap离开屏幕可视范围时候(onDetachWindow等时候),去做unpin.

Fresco还提供了哪些实用功能?

1. 加载和展示GIF,WebP;

2. 分别控制4个角的不同圆角;

3. 把图片切成圆形;

4. focusCrop,从指定的focus位置做类似centerCrop的scaleType;

5. 图片加载进度条,类似我们看新浪微博客户端GIF图片加载过程的那种进度,可自定义样式;

6. 点击加载失败的图片,可重新加载;

具体更多的能力提供,参考Fresco官方网页.

对比Fresco和Picasso

package com.example.garena.myapplication;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView; import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.view.SimpleDraweeView;
import com.squareup.picasso.Picasso; import java.util.ArrayList; public class MainActivity extends ActionBarActivity {
private static final ArrayList<String> URL_LIST = new ArrayList<>();
static {
URL_LIST.add("http://upload.wikimedia.org/wikipedia/en/thumb/7/7a/Manchester_United_FC_crest.svg/1010px-Manchester_United_FC_crest.svg.png");
URL_LIST.add("http://www.newstylesports.com/wp-content/uploads/2014/09/Manchester-United-Salary-2014.jpg");
URL_LIST.add("http://www.businessofsoccer.com/wp-content/uploads/2013/06/Manchester-United-Logo-Full-HD-Wallpaper.jpg");
URL_LIST.add("http://createapk.com/project/2014/07/lightkretek/manchester-united-wallpapers/image/104267-manchester-united-wallpapers.jpg");
URL_LIST.add("http://i2.manchestereveningnews.co.uk/incoming/article339323.ece/alternates/s2197/Manchester-United.jpg");
URL_LIST.add("http://www.thedrum.com/uploads/drum_basic_article/156824/main_images/ManchesterUnitedLogo_0.png");
URL_LIST.add("http://www.manutd.com/~/media/7317FC0A0B9B4A8ABD47E29E8E47D5EA.ashx?w=2560&h=1600");
URL_LIST.add("http://niaje.com/wp-content/uploads/2015/02/manu.jpg");
URL_LIST.add("http://teamspictures.com/wp-content/uploads/2015/03/Manchester-united-Football-Club-Wallpaper.jpg");
URL_LIST.add("http://g.foolcdn.com/editorial/images/146745/manchester-united-stock_large.PNG");
URL_LIST.add("http://i2.mirror.co.uk/incoming/article4918329.ece/ALTERNATES/s1227b/Yeovil-v-Manchester-United.jpg");
URL_LIST.add("http://worldsoccertalk.com/wp-content/uploads/2014/01/manchester-united.jpg");
URL_LIST.add("http://i.dailymail.co.uk/i/pix/2014/09/03/1409773352229_wps_66_Cristiano_Ronaldo_of_Manc.jpg");
URL_LIST.add("http://i.guim.co.uk/static/w-620/h--/q-95/sys-images/Football/Pix/pictures/2014/10/5/1412513201728/Radamel-Falcao-celebrates-010.jpg");
URL_LIST.add("http://i.dailymail.co.uk/i/pix/2014/09/13/1410639943046_wps_18_MANCHESTER_ENGLAND_SEPTEM.jpg");
URL_LIST.add("http://www.manutd.com/sitecore/shell/~/media/CCE3892A29474CB7A126398691568B19.ashx?w=480&h=270&rgn=0,130,800,581");
URL_LIST.add("http://img.skysports.com/14/07/660x350/manchester-united-team-los-angeles-galaxy-la_3177246.jpg");
URL_LIST.add("http://i.dailymail.co.uk/i/pix/2014/08/02/1407019617274_wps_31_Manchester_United_defende.jpg");
URL_LIST.add("http://static.guim.co.uk/sys-images/Guardian/Pix/pictures/2013/11/27/1385582053011/Bayer-Leverkusen-v-Manche-002.jpg");
URL_LIST.add("http://www.simbasports.co.uk/wp-content/uploads/2013/08/Manchester-United.jpg");
URL_LIST.add("http://www.footballwood.com/wp-content/uploads/2014/07/Manchester-United-2014-pre-season-schedule-fixtures.jpg");
URL_LIST.add("https://lh5.googleusercontent.com/-HM991djPFX4/UTbiLMwiuNI/AAAAAAAAAFs/GFlG8v56TT0/w800-h800/Manchester%2BUnited%2Bin%2BNaruto%2BWallpaper.jpg");
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide(); ListView listView = (ListView) findViewById(R.id.fresco_list_view);
Adapter adapter = new Adapter(this, URL_LIST);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}private static class Adapter extends BaseAdapter {
private final ArrayList<String> mUrlList;
private final LayoutInflater mInflater;
private final Context mContext; public Adapter(Context context, ArrayList<String> urlList) {
mUrlList = urlList;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mContext = context;
} @Override
public int getCount() {
return mUrlList.size();
} @Override
public String getItem(int position) {
return mUrlList.get(position);
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.fresco_item, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Uri uri = Uri.parse(getItem(position));
// viewHolder.draweeView.setImageURI(uri);
// viewHolder.normalImageView.setVisibility(View.GONE); Picasso.with(mContext).load(uri).into(viewHolder.normalImageView);
viewHolder.draweeView.setVisibility(View.GONE);
return convertView;
} private static class ViewHolder {
private final SimpleDraweeView draweeView;
private final ImageView normalImageView; public ViewHolder(View view) {
draweeView = (SimpleDraweeView) view.findViewById(R.id.fresco_image_view);
normalImageView = (ImageView) view.findViewById(R.id.normal_image_view);
}
}
}
}

上面是一个非常简单的Activity,一个ListView展示一个列表的网络图片.

Android2.3.7,Fresco:

Android Fresco (Facebook开源的图片加载管理库)

Android2.3.7,Picasso:

Android Fresco (Facebook开源的图片加载管理库)

Android4.4.4,Fresco:

Android Fresco (Facebook开源的图片加载管理库)

Android4.4.4,Picasso:

Android Fresco (Facebook开源的图片加载管理库)

Android5.1,Fresco:

Android Fresco (Facebook开源的图片加载管理库)

Android5.1,Picasso:

Android Fresco (Facebook开源的图片加载管理库)

从上面的对比中发现:

1. Android2.3.7,Fresco反而内存占用比Picasso高.

2. Android4.4.4,Fresco完胜Picasso,无论怎么滚动ListView展示图片,内存都是静止的一条直线.

3. Android5.1,Fresco和Picasso不相伯仲.这是因为Fresco没有使用Ashmem.

Fresco至于我的疑虑

最后,Fresco让我疑虑的一点是,粗略查看了Fresco提供的能力,貌似木有发现有类似Picasso.pauseTag和resumeTag的API.

这两个API对于scrolling的操作非常重要.当scrolling的时候,应该暂停图片的加载的线程,当滚动停止时才恢复图片加载的线程运行.

Android Fresco (Facebook开源的图片加载管理库)的更多相关文章

  1. Android开发三种第三方图片加载的框架

    最近在项目中用到了大量图片加载,第三方优秀框架还不错,下面介绍三款榜首的框架用法和问题,做一个记录. 现在项目使用的是Android Studio开发的,现在也没有多少人使用Eclipse了吧. 一. ...

  2. Fresco&comma;Facbook强大的图片加载框架

    项目git地址:https://github.com/facebook/fresco Fresco是 facebook推出的一款强大的图片加载的框架:主要有Image Pipeline和Drawees ...

  3. imagepool前端图片加载管理器&lpar;JavaScript图片连接池&rpar;

    前言 imagepool是一款管理图片加载的JS工具,通过imagepool可以控制图片并发加载个数. 对于图片加载,最原始的方式就是直接写个img标签,比如:<img src="图片 ...

  4. Android开发笔记&mdash&semi;&mdash&semi;以Volley图片加载、缓存、请求及展示为例理解Volley架构设计

    Volley是由Google开源的.用于Android平台上的网络通信库.Volley通过优化Android的网络请求流程,形成了以Request-RequestQueue-Response为主线的网 ...

  5. Android 开发 框架系列 Android-Universal-Image-Loader 图片加载使用demo

    Android-Universal-Image-Loader github地址:https://github.com/nostra13/Android-Universal-Image-Loader 加 ...

  6. Android图片加载库的理解

    前言     这是“基础自测”系列的第三篇文章,以Android开发需要熟悉的20个技术点为切入点,本篇重点讲讲Android中的ImageLoader这个库的一些理解,在Android上最让人头疼是 ...

  7. Android之Fresco(facebook的强大Android图片加载的框架)

    Fresco是Facebook最新推出的一款用于Android应用中展示图片的强大图片库,可以从网络.本地存储和本地资源中加载图片.其中的Drawees可以显示占位符,直到图片加载完成.而当图片从屏幕 ...

  8. Android图片加载神器之Fresco,基于各种使用场景的讲解

    Fresco是Facebook开源Android平台上一个强大的图片加载库,也是迄今为止Android平台上最强大的图片加载库. 优点:相对于其他开源的第三方图片加载库,Fresco拥有更好的内存管理 ...

  9. Android图片加载神器之Fresco, 基于各种使用场景的讲解

    Fresco是Facebook开源Android平台上一个强大的图片加载库,也是迄今为止Android平台上最强大的图片加载库. 优点:相对于其他开源的第三方图片加载库,Fresco拥有更好的内存管理 ...

随机推荐

  1. Android开发中的Json字符串与复杂的嵌套对象互转。

    Gson 可能是大家都觉得比较简单吧.我发现用JSONObject和网上下载的JSONHelper类使用起来很无语,只能解析简单的单层对象,如果有嵌套的就不能直转转成可用对象了.所以网上找了一会儿,发 ...

  2. Spring-涉及到的设计模式汇总

    1. 简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类. ...

  3. centos下安装五笔输入法的教程

    [root@ok ~]# yum update [root@ok ~]# yum install ibus-table-chinese-wubi-haifeng 以上两步已经成功!! #yum ins ...

  4. mysql版sql助记

    新建用户 CREATE USER 'username'@'host' IDENTIFIED BY 'password'; [host 中 使用 % 为通配符, 匹配任意远程主机] 赋权 GRANT p ...

  5. C&num;的百度地图开发&lpar;一&rpar;发起HTTP请求

    原文:C#的百度地图开发(一)发起HTTP请求 百度地图的开发文档中给出了很多的事例,而当用到具体的语言来开发时,又会有些差异.我是使用C#来开发的.在获取相应的数据时,需要通过URL传值,然后获取相 ...

  6. html块级元素和内联元素区别详解

    块级元素(block)特性: 总是独占一行,表现为另起一行开始,而且其后的元素也必须另起一行显示; 宽度(width).高度(height).内边距(padding)和外边距(margin)都可控制; ...

  7. Linux系列教程(八)——Linux常用命令之压缩和解压缩命令

    前面一篇博客我们讲解了Linux帮助和用户管理命令,对于帮助命令,man 命令能获得命令和配置文件的帮助信息,help命令能获得shell内置命令的帮助信息.我们可以通过which来区分什么是shel ...

  8. 在Node&period;js中操作文件系统&lpar;一&rpar;

    在Node.js中操作文件系统 在Node.js中,使用fs模块来实现所有有关文件及目录的创建,写入及删除操作.在fs模块中,所有对文件及目录的操作都可以使用同步与异步这两种方法.比如在执行读文件操作 ...

  9. 《精通Python设计模式》学习结构型之MVC模式

    这个就不需要多评论了, 哪个主流的PYTHON的WEB框架都有这些模式实现哈. quotes = ('A man is not complete until he is married. Then h ...

  10. C&plus;&plus; GDI&plus;调用

    封装了一个GDI+的使用类 GdiPluss.h #pragma once #include <comdef.h> #include <gdiplus.h> using nam ...