XUtils BitmapUtils 改造以加入drawable支持
=== XUtilsBitmapUtils 改造以加入drawable支持 ===
# XUtils 简单介绍
XUtils 是一套少有的早期国产安卓框架, 其源于AFinal, 文件夹结构也与之相似, 可是代码却进行了大量的重构, 使得XUtils更加现代, 攻克了AFinal 的OOM等问题.
眼下 XUtils 已经支持 API 8(android 2.2) 至 API 21(android 5.0.x).
XUtils 主要内置了DbUtils 模块, ViewUtils 模块, HttpUtils 模块, BitmapUtils 模块.
对于新手来说, 这些功能着实使用并且强大, 为我们省下了不少的功夫 去处理业务.
同类的框架, 国外流行的的有androidannotations, roboguice, androidquery,droidparts等, 当然国内也有不少竞争者,
ThinkAndroid,UltimateAndroid, LoonAndroid, KJFrameForAndroid, SmartAndroid, 都是能够能够用来借鉴的. 本文临时专注于XUtils的使用.
详细的细化模块能够參考 官方地址(wyouflf/xUtils):
https://github.com/wyouflf/xUtils
做过android的同学一定都知道安卓处理Bitmap可谓一绝, Bitmap绝对是吃内存的大户, 并且Dalvik虚拟机(临时不考虑ART技术)垃圾回收常常不及时, 所以图片处理不当,常常会出现OOM(out of memory), 即内存溢出的情况. 在接触XUtils等框架之前, 非常多人都是自己通过BitmapFactory.Options 来解决燃眉之急, 网上也有非常多对策, 可是这样非常不系统, 并且有些方案, 比如使用软引用或者弱引用, 已经在安卓4之后不再被推荐(事实上com.lidroid.xutils.bitmap.core.AsyncDrawable.java
还是用了弱引用), 仍然可能会出现OOM. 所以一款流行的, 稳定的, 现代的代码框架是不可缺少的. XUtils 恰恰满足了这一点.
XUtils 的图片处理存在缓存, 主要是内存缓存和外存缓存. 可是这不是今天本文的重点, 可是以后会提及. 今天主要说说XUtils不太好的方面, 首先直接上改动过的官方代码:
// this 是一个 Context
BitmapUtils bitmapUtils = new BitmapUtils(this);
// 载入网络图片
bitmapUtils.display(testImageView,"http://www.52deng.com/logo.png");
bitmapUtils.display(testImageView,"ftp://www.52deng.com/logo.png");
// 载入本地图片, 路径以/开头, 须要填写绝对路径
bitmapUtils.display(testImageView,"/sdcard/dengdeng/test.jpg");
// 载入assets中的图片, 路径以assets开头
bitmapUtils.display(testImageView,"assets/dengdeng/wallpaper.jpg");
// 使用ListView等容器展示图片时, 可通过PauseOnScrollListener在滑动和高速滑动过程中控制暂停载入图片
listView.setOnScrollListener(newPauseOnScrollListener(bitmapUtils, false, true));
listView.setOnScrollListener(newPauseOnScrollListener(bitmapUtils, false, true, customListener));
凝视已经被我优化, 相信结合代码, 语义应该更加明朗了. (← 你够了, 语文渣)
可是细致观察会发现, 事实上UXtils还是有不完美的地方: 貌似并不支持从项目中的drawable获取图片进行展示, 这样岂不是遇到大图片又要回归BitmapFactory.Options等基础方案了吗?
这里给大家推荐一下还有一个安卓专攻图片处理的框架Android-Universal-Image-Loader, 官方地址例如以下:
https://github.com/nostra13/Android-Universal-Image-Loader,
看关注度就能看出来, 它在Github上处于垄断地位, 当然还有其它的专攻网络和图片异步的框架(国外的有glide, ion, Picasso,volley等), 都是非常厉害和出名的. 那么我们来看看 他支持的图片处理方案, 不改了, 直接引用官方的样例:
"http://site.com/image.png"// from Web
"file:///mnt/sdcard/image.png"// from SD card
"file:///mnt/sdcard/video.mp4"// from SD card (video thumbnail)
"content://media/external/images/media/13"// from content provider
"content://media/external/video/media/13"// from content provider (video thumbnail)
"assets://image.png"// from assets
"drawable://"+ R.drawable.img//
fromdrawables (non-9patch images)
NOTE: Use drawable:// only
if you really need it! Always considerthe native way toload drawables -ImageView.setImageResource(...) instead
of using of ImageLoader.
看, 他是 支持多种图片协议或者存储路径的, 也包含drawable, 可是值得注意的是, 他事实上并不推荐缓存drawable, 依据我的理解, 毕竟有一些drawable非常小, 直接使用 ImageView 等空间自带的放置图片的方法就可以. 可是遇到OOM的话, 该出手时就出手. 因为时间紧迫, 临时不细研究这款开源项目的设计, 直接扒代码. 检出项目之后, Ctrl+H选择项目, 全文搜索 keyword”drawable://”.
结果出来一堆东西, 换个思路, 搜索”assets://”, 竟然找到的是样例, 再换思路, 搜索”assets:”, ok, 侥幸找到了核心代码 (事实上他是通过 scheme 匹配传递的url的协议的):
// com.nostra13.universalimageloader.core.download.BaseImageDownloader.java
@Override
public InputStream getStream(String imageUri,Objectextra) throws
IOException{
switch (Scheme.ofUri(imageUri)) {
case HTTP:
case HTTPS:
return getStreamFromNetwork(imageUri,extra);
case FILE:
return getStreamFromFile(imageUri,extra);
case CONTENT:
return getStreamFromContent(imageUri,extra);
case ASSETS:
return getStreamFromAssets(imageUri,extra);
case DRAWABLE:
return getStreamFromDrawable(imageUri,extra);
case UNKNOWN:
default:
return getStreamFromOtherSource(imageUri,extra);
}
}
好吧, 把DRAWABLE看看:
protected InputStream getStreamFromDrawable(String imageUri,Objectextra)
{
String
drawableIdString = Scheme.DRAWABLE.crop(imageUri);
int drawableId =Integer.parseInt(drawableIdString);
return context.getResources().openRawResource(drawableId);
}
OK了, 那么来匹配一下 Xutils, 开启Ctrl+H全文搜索打开, 搜索”assets”, 轻松找到了:
// com.lidroid.xutils.bitmap.download.DefaultDownloader.java
if (uri.startsWith("/")) {
FileInputStream fileInputStream =newFileInputStream(uri);
fileLen =
fileInputStream.available();
bis =
new BufferedInputStream(fileInputStream);
result =
System.currentTimeMillis() +
this.getDefaultExpiry();
} else
if (uri.startsWith("assets/")) {
InputStream
inputStream = this.getContext().getAssets().open(uri.substring(7,uri.length()));
fileLen =
inputStream.available();
bis =
new BufferedInputStream(inputStream);
result =
Long.MAX_VALUE;
} else {
final URLurl =newURL(uri);
urlConnection =url.openConnection();
urlConnection.setConnectTimeout(this.getDefaultConnectTimeout());
urlConnection.setReadTimeout(this.getDefaultReadTimeout());
bis =
new BufferedInputStream(urlConnection.getInputStream());
result =
urlConnection.getExpiration();
result =
result < System.currentTimeMillis() ?System.currentTimeMillis() +this.getDefaultExpiry()
:result;
fileLen =
urlConnection.getContentLength();
}
}
有了前几步的经验, 轻松改造, 加一个else if, 代码 參考之前的Android-Universal-Image-Loader的核心代码:
if (uri.startsWith("/")) {
FileInputStream fileInputStream =newFileInputStream(uri);
fileLen =
fileInputStream.available();
bis =
new BufferedInputStream(fileInputStream);
result =
System.currentTimeMillis() +
this.getDefaultExpiry();
} else
if (uri.startsWith("assets/")) {
InputStream
inputStream = this.getContext().getAssets().open(uri.substring(7,uri.length()));
fileLen =
inputStream.available();
bis =
new BufferedInputStream(inputStream);
result =
Long.MAX_VALUE;
} else
if (uri.startsWith("drawable://")) {//赤裸裸地抄袭,我也用这个协议
String
drawableIdString = uri.substring(11,uri.length());//注意别算错了
int drawableId =Integer.parseInt(drawableIdString);
//还原原始的 id
InputStream
inputStream = this.getContext().getResources().openRawResource(drawableId);
fileLen =
inputStream.available();//抄上面的
bis =
new BufferedInputStream(inputStream); //抄上面的
result =
Long.MAX_VALUE;//抄上面的,先这么写,以后讨论
} else {
final URLurl =newURL(uri);
urlConnection =url.openConnection();
urlConnection.setConnectTimeout(this.getDefaultConnectTimeout());
urlConnection.setReadTimeout(this.getDefaultReadTimeout());
bis =
new BufferedInputStream(urlConnection.getInputStream());
result =
urlConnection.getExpiration();
result =
result < System.currentTimeMillis() ?System.currentTimeMillis() +this.getDefaultExpiry()
:result;
fileLen =
urlConnection.getContentLength();
}
}
轻松改造, TEST!!
String uri = "drawable://" +R.drawable.super_larger_logo;
BitmapHelp.getBitmapUtils(this).display(largePic_imgV, uri);
OK, 測试通过, 图片出现, 未出现OOM. 至此, 成功地加入drawable支持. 同理, 我们也能够抄抄”content”等协议的代码, 本文就不赘述了, 注意源码的协议, 引用或者改动都要留出处啊.
2015-03-14 PS: 注意不要对 *.9.png 套用, 这非常没有必要, *.9.png 通常非常小. 此外 对图片实时性要求高的也不可用上面的方案, 尽管能解决 内存溢出和卡顿, 可是 播放连贯性 和 用户体验等会打大折扣的.
Presented by imknown
2015-03-13
XUtils BitmapUtils 改造以加入drawable支持的更多相关文章
- 痞子衡嵌入式:其实i.MXRT下改造FlexSPI driver同样支持AHB方式去写入NOR Flash
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下改造FlexSPI driver以AHB方式去写入NOR Flash. 痞子衡前段时间写过一篇 <串行NAND Fl ...
- 3. Android框架和工具之 xUtils(BitmapUtils)
1. BitmapUtils 作用: 加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象: 支持加载网络图片和本地图片: 内存管理使用 ...
- xUtils类库的使用
序言: 作为一个职业的程序猿,不会像新手一样把每一个需要实现的功能每次重写一遍,因为程序猿能熟练的使用各种第三方类库. 毕竟人类因为会使用工具才站到了食物链顶端. 现在就让我们学习使用xUtils类库 ...
- Xutils 源码解析【转】
原文:http://my.oschina.net/u/1538627/blog/395098 目录[-] 1. 功能介绍 2. 详细设计 2.1 View模块 2.1.1 总体设计 2.1.2 流程图 ...
- xUtils 源码解析
1. 功能介绍 xUtils 一个 Android 公共库框架,主要包括四个部分:View,Db, Http, Bitmap 四个模块. View 模块主要的功能是通过注解绑定 UI,资源,事件. D ...
- (原创)RecyclerView结合xUtils2.6实现滚动时不加载item,xUtils2.6的源码分析与改造
我们知道xUtils中的bitmapUtils与listview相配合可以实现滚动时暂停加载 只需要一句话: listview.addOnScrollListener(new PauseOnScrol ...
- 代码二次封装-xUtils(android)
通常我们会引用很多lib 而且会出现lib 与我们的功能仅仅差一点点 这种情况我们最好不要去改动源代码 而是进行二次封装 举例我使用 xUtils的二次封装 此处说明我是搞ios的 这个是androi ...
- Android开发框架之xUtils学习
1.一个非作者弄的xUtils API文档: http://xutilsapi.oschina.mopaas.com/overview-summary.html 2.使用xUtils用户的一些博客文档 ...
- XAMPP支持多PHP版本
在使用xampp进行开发的时候,我们都知道它只能支持一个PHP版本不能像PHPstudy那样方便进行不同版本的切换操作.因此我们手动的对于xampp进行改造一下,使其支持其他PHP版本 1. 从官网上 ...
随机推荐
- server 08 R2 NBL 报错:RPC 服务器在指定计算机上不可用
排查步骤如下: 1.检查并确保 Remote Procedure Call (RPC) 和 Remote Procedure Call (RPC) Locator这两项服务是否都已经启动 2.确认此2 ...
- Scrapy 应用之爬取《盗墓笔记》
爬取<盗墓笔记>和爬取<宦海沉浮>原理一样,但是使用了两种不同的追踪链接的方式,<盗墓笔记>使用的是跟踪下一页链接,直至没有下一页为止,<宦海沉浮>则是 ...
- 循环神经网络与LSTM网络
循环神经网络与LSTM网络 循环神经网络RNN 循环神经网络广泛地应用在序列数据上面,如自然语言,语音和其他的序列数据上.序列数据是有很强的次序关系,比如自然语言.通过深度学习关于序列数据的算法要比两 ...
- 九度oj 题目1014:排名
题目描述: 今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑每题的分值,所以并不是最后的排名.给定录取分数线,请你写程序找出最后通过分数线的考生,并将他 ...
- CentOS 7.0如何安装配置iptables和seLinux以及firewalld
一.配置防火墙,开启80端口.3306端口 CentOS .0默认使用的是firewall作为防火墙,这里改为iptables防火墙. .关闭firewall: systemctl stop fire ...
- Nginx+Php中限制站点目录防止跨站的配置方案记录
Nginx+Php中限制站点目录防止跨站的配置方案记录(使用open_basedir)-------------------方法1)在Nginx配置文件中加入: 1 fastcgi_param PH ...
- EXPDP/IMPDP任务的查看与管理
EXPDP/IMPDP相比传统的exp/imp的最本质区别在于服务器端执行,客户端发出指定后,通过API启动服务器的备份job,在执行过程中,可以拿下Ctrl+C组合键,退出当前交互模式,退出之后,导 ...
- Oracle 数据库有五个必需的后台进程,DBWR,LGWR,CKPT,SMON,PMON
SMON 是系统监视器(System Monitor)的缩写.如果Oracle实例失败,则在SGA中的任何没有写到磁盘中的数据都会丢失.有许多情况可能引起Oracle实例失败,例如,操作系统的崩溃就会 ...
- bzoj1064【Noi2008】假面舞会
题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1064 给一个有向图染色,每个点的后继必须相同,问至少&至多有多少种染色方案 sol: ...
- Morris Traversal 方法遍历二叉树(非递归、不用栈,O(1)空间)
http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html