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

时间: 2024-10-29 00:22:33

XUtils BitmapUtils 改造以加入drawable支持的相关文章

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 模块, HttpUti

springCloud分布式事务实战(七)改造合服务BlockMicroService支持分布式事务

在BlockMicroService 工程 中加入(1)加入jar <!-- springCloud 事务 关键点1 --> <dependency> <groupId>com.codingapi</groupId> <artifactId>transaction-springcloud</artifactId> <version>${lcn.last.version}</version> <exclus

Xutils 源码解析【转】

原文:http://my.oschina.net/u/1538627/blog/395098 目录[-] 1. 功能介绍 2. 详细设计 2.1 View模块 2.1.1 总体设计 2.1.2 流程图 2.1.3 核心类功能介绍 请先了解注解 ,动态代理 可以帮助到您, 如果已经了解请忽略. 1.ViewUtils.java (1)主要函数 2.ViewFinder.java (1)主要函数 3.ResLoader.java 4.EventListenerManager.java 5.注解类 2

Xutils

实体类  用ViewUtils附加了注解  DbUtils可以直接创建数据库根据实体类的注解创建数据库的表 1 package com.qianfeng.xutilsshow.model; 2 3 import com.lidroid.xutils.db.annotation.Column; 4 import com.lidroid.xutils.db.annotation.Id; 5 import com.lidroid.xutils.db.annotation.Table; 6 7 8 /*

代码二次封装-xUtils(android)

通常我们会引用很多lib 而且会出现lib 与我们的功能仅仅差一点点 这种情况我们最好不要去改动源代码 而是进行二次封装 举例我使用 xUtils的二次封装 此处说明我是搞ios的 这个是android 今天mac 机子没网 蛋疼 使用到pulltorefresh 和 xUtils 网络封装 因为此处是没有文件处理所以我把參数转换里面file给去掉了 假设须要自行加上就可以 public class ApiHttpUtil { final public static String base_ur

Android 应用层开发 Drawable 的一些叨叨絮

1 背景 博客也该开张了,懒惰都是惯的.既然这样,那就拿一个简单问题来叨叨絮吧:故事的起因是这样的,群里有一哥们仿写别人自定义控件,没整明白 Drawable 咋回事,然后群里炸开了锅,为了维护群里的世界和平,随决定叨叨絮一下 Android Drawable.关于 Android Drawable 可绘制对象资源的介绍大家可以去看看官方文档即可:而关于 Drawable 的使用细节其实你在 Drawable.java 的开篇大段注释中可以找寻到秘笈,所以说,如果你想玩转 Android 自定义

Android开发之xUtils学习

1.一个非作者弄的xUtils API文档: http://xutilsapi.oschina.mopaas.com/overview-summary.html 2.使用xUtils用户的一些博客文档: xUtils – 注解的使用和说明--http://abug.aliapp.com/?p=78 xUtils – HttpUtils的使用(一)--http://abug.aliapp.com/?p=61 xUtils – HttpUtils的使用(二)--http://abug.aliapp.

IPv6升级改造包括什么?

关于IPv6技术升级具体做了什么,在我脑海里只是更换了域名解析的IP而已,所以找了这篇文章,帮助初步解惑. 原文地址:https://www.maczd.com/post/web-ipv6-upgrading.html#prettyPhoto 网际协议第六版 IPv6(Internet Protocol version 6)是最新的互联网协议,协议标准最早诞生于 1998 年 12 月.IPv6 的出现解决了 IPv4 地址枯竭的问题和提升网络传输效率,不过由于开始时期 IPv6 的标准复杂以及

【入门】广电行业DNS、DHCP解决方案详解(五)——IPv6趋势下DHCP改造指南

DHCPv6相关知识 DHCPv6与DHCPv4对比 IP地址管理(IPAM) 现存挑战 解决思路 现在国家要求广电网络的终端要实现IPv6,第一阶段要实现IPv6的双栈化,第二或第三阶段要完全去IPv4化.这就涉及到CM.终端PC和机顶盒,都要进行IPv6改造,都要支持双栈的部署,DHCP也要支持IPv6的地址分配和认证. DHCPv6相关知识 IPv6网络架构下DHCPv6已成为必不可少的核心业务枢纽,我们先对DHCPv6进行简单介绍: DHCPv6是一个用来配置工作在IPv6网络上的IPv