Android加载网络图片,能自动生成缩略图吗

Android加载网络图片,能自动生成缩略图吗,第1张

不能自动加载缩略图。

一般的处理逻辑是你的服务器要支持处理,比如你在url后面跟一个想要的尺寸(100x100),服务器就能返回一个处理后尺寸接近100x100的给你。

对比现在主流框架的优势和缺点,在实际项目中如何选择适合自己的框架;

Glide、Fresco、Picasso、ImageLoader

共同优点:

以上名词介绍

在分析他们的差异、优缺点之前,我们先了解缓存通用的概念:

以上概念在不同框架之间可能不同,比如Displayer在ImageLoader中叫做ImageAware,在Picasso和Glide中叫做Target。

以上为Glide的总体设计图。

整个库分为RequestManager(请求管理器)、Engine(数据获取引擎)、Fetcher(数据获取器)、MemoryCache(内存缓存)、DiskLRUCache(本地缓存)、Transformation(处理)、Encoder(编码处理)、Registry(类型以及解析器配置)、Target(目标)等模块。

简单流程: Glider收到加载及显示资源任务,创建Request并将它交给RequestManager,Request启动Engine去数据源获取资源,得到资源后通过Transformation处理后交给Target

Glide依赖DiskLRUCache、GifDecoder等开源库去完成本地缓存和Gif解密工作;

为Bitmap 维护一个BitmapPool对象池, 对象池的主要目的是通过减少大对象的分配以重用来提高性能!

缺点

①质量低:因为机制不同,速度快,但是的质量降低了RGB565;

②多尺寸缓存导致内存和磁盘占用多:根据ImageView大小来缓存,可能会导致一张可能根据展示情况来缓存不同尺寸的几份;

扩展理解参考: >

1、程序,把Assets中的图像显示出来

try {

BufferedInputStream bis = new BufferedInputStream(getAssets()

open("abmp"));

Bitmap bm = BitmapFactorydecodeStream(bis);

imageView01setImageBitmap(bm);

} catch (Exception e) {

// TODO Auto-generated catch block

eprintStackTrace();

Systemoutprintln("==========file not found======");

}

2、原理:Android中的资源分析

资源是Android应用程序中重要的组成部分。在应用程序中经常会使用字符串、菜单、图像、声音、视频等内容,都可以称之为资源。通过将资源放到与apk文件中与Android应用程序一同发布,在资源文件比较大的情况下,可以通过将资源作为外部文件来使用,我们将分析如何在Android应用程序中存储这些资源。

一、资源的存储

在android中,资源大多都是保存在res目录中,例如布局资源以XML文件的形式保存在res\layout目录中;图像资源保存着res\drawable目录中;菜单资源保存在res\menu目录中。ADT在生成apk文件时,这些目录中的资源都会被编译,然后保存到apk文件中。如果将资源文件放到res\raw目录中,资源将在不编译的情况下放入apk文件中。在程序运行时可以使用InputStream来读取res\raw目录中的资源。

如果使用的资源文件过大,我们可以考虑将资源文件作为外部文件单独发布。Android应用程序会从手机内存或者SD卡读取这些资源文件。

二、资源的种类

从资源文件的类型来划分,我们可以将资源文件划分为XML、图像和其它。以XML文件形式存储的资源可以放在res目录中的不同子目录里,用来表示不同种类的资源;而图像资源会放在res\drawable目录中。除此之外,可以将任意的资源嵌入Androidy应用程序中。比如音频和视频等,一般这些资源放在res\raw目录中。

表1、 Android支持的资源

目录 资源类型 描述

Res\values

XML

保存字符串、颜色、尺寸、类型、主题等资源,可以是任意文件名。对于字符串、颜色、尺寸等信息采用

Key-value形式表示,对于类型、主题等资源,采用其它形式表示

Res\layout

XML

保存布局信息。一个资源文件表示一个View或ViewGroup的布局

Res\menu

XML

保存菜单资源。一个资源文件表示一个菜单(包括子菜单)

Res\anim

XML

保存与动画相关的信息。可以定义帧(frame)动画和补间(tween)动画

Res\xml

XML

在该目录的文件可以是任意类型的XML文件,这些XML文件可以在运行时被读取。

Res\raw

任意类型

在该目录中的文件虽然也会被封装在apk文件中,但不会被编译。在该目录中可以放置任意类型的文件,例如,各种类型的文档、音频、视频文件等

Res\drawable

图像

该目录中的文件可以是多种格式的图像文件,例如,bmp、png、gif、jpg等。在该目录中的图像不需要分辨率非常高,aapt工具会优化这个目录中的图像文件。如果想按字流读取该目录下的图像文件,需要将图像文件放在res\raw目录中。

assets

任意类型

该目录中的资源与res\raw中的资源一样,也不会被编译。但不同的是该目录中的资源文件都不会生出资源ID

三、资源文件的命名

每一个资源文件或资源文件中的key-value对都会在ADT自动生成的R类(在Rjava文件中)中找到相对应的ID其中资源文件名或key-value对中的key就是R类中的java变量名。因此,资源文件名好key的命名首先要符合java变量的命名规则。

除了资源文件和key本身的命名要遵循相应的规则外,多个资源文件和key也要遵循唯一的原则。也就是说,同类资源的文件名或key不能重复。例如,两个表示字符串资源的key不能重复,就算这两个key在不同的XML文件中也不行。

由于ADT在生成ID时并不考虑资源文件的扩展名,因此,在res\drawable、res\raw等目录中不能存在文件名相同,扩展名不同的资源文件。例如在res\drawable目录不能同时放置iconjpg和iconpng文件。

四、资源使用示例

在Android SDK中不仅提供了大量的系统资源,而且还允许开发人员定制自己的资源。不管是系统资源,还是自定义的资源,一般都会将这些资源放在res目录中,然后通过R类中的相应ID来引用这些资源。接下来将针对于XML类资源的使用进行分析。

XML资源实际上就是XML格式的文本文件,这些文件必须放在res\xml目录中。可以通过ResourcesgetXml方法获得处理指定XML文件的XmlResourceParser对象。实际上,XmlResourceParser对象处理XML文件的的过程主要是针对不同的状态点处理相应的代码,比如开始分析文档、开始分析标签、分析标签完成等,XmlResourceParser通过调用next方法不断更新当前的状态。

下面的代码,则是展示如何读取res\xml目录中的XML文件的内容,先在res\xml目录中建立一个xml文件。将AndroidManifestxml文件复制到res\xml目录中,并改名为androidxml。

在准备完XML文件后,在onCreate方法中开始读取XML文件的内容,代码如下:

public void onCreate(Bundle savedInstanceState)

{

superonCreate(savedInstanceState);

setContentView(Rlayoutmain);

TextView textView=(TextView)findViewById(Ridtextview);

StringBuffer sb=new StringBuffer();

// 获得处理android。xml文件的XmlResourceParser对象

XmlResourceParser xml=getResources()getXml(Rxmlandroid);

try

{

//切换到下一个状态,并获得当前状态的类型

int eventType =xmlnext();

while(true)

{

//文档开始状态

if(eventType == XmlPullParserSTART_DOCUMENT)

{

Logd("start_document","start_document");

}

//标签开始状态

else if(eventType ==XmlPullParserSTART_TAG)

{

Logd("start_tag",xmlgetName());

//将标签名称和当前标签的深度(根节点的depth是1,第2层节点的depth是2,类推)

sbappend(xmlgetName()+"(depth:"+xmlgetDepth()" ");

//获得当前标签的属性个数

int count=xmlgetAttributeCount();

//将所有属性的名称和属性值添加到StringBuffer对象中

for(int i=0;i<count;i++)

{

sbappend(xmlgetAttributeName(i)+":

"+xmlgetAttributeValue(i)+"");

}

sbappend(")\n");

}

//标签结束状态

else if(eventType ==XmlPullParserEND_TAG)

{

Logd("end_tag",xmlgetName());

}

//读取标签内容状态

else if(eventType ==XmlPullParserTEXT)

{

Logd("text","text");

}

//文档结束状态

else if(eventType ==XmlPullParserEND_DOCUMENT)

{

Logd("end_document","end_document");

//文档分析结束后,退出while循环

break;

}

//切换到下一个状态,并获得当前状态的类型

eventType =xmlnext();

}

textViewsetText(sbtoString());

}

catch(Exception e) {}

}

二、如果想读入文件

在使用getAssets()open("anhuixml")返回输人流之后,就可以以此为参数,后面的处理跟普通的java的处理相同。

这个方法用来将特定格式的压缩写入输出流(OutputStream)中,当然例如输出流与文件联系在一起,压缩后的也就是一个文件。如果压缩成功则返回true,其中有三个参数:

format是压缩后的的格式,可取值:BitmapCompressFormat JPEG、~PNG、~WEBP。

quality的取值范围为[0,100],值越小,经过压缩后失真越严重,当然文件也会越小。(PNG格式的会忽略这个值的设定)

stream指定压缩的输出的地方,比如某文件。

上述方法还有一个值得注意的地方是:当用BitmapFactory decode文件时可能返回一个跟原不同位深的,或者丢失了每个像素的透明值(alpha),比如说,JPEG格式的仅仅支持不透明的像素。文章android压缩在文末提到的下面这点可能就是这个原因:

当调用bitmapcompress(CompressFormatJPEG, 100, fos);保存为时发现背景为黑色,如下图:

这时只需要改成用png保存就可以了,bitmapcompress(CompressFormatPNG, 100, fos);,如下图:

下面是质量压缩的代码:

public static void compressBmpToFile(Bitmap bmp,File file){

ByteArrayOutputStream baos = new ByteArrayOutputStream();

int options = 80;//个人喜欢从80开始,

bmpcompress(BitmapCompressFormatJPEG, options, baos);

while (baostoByteArray()length / 1024 > 100) {

baosreset();

options -= 10;

bmpcompress(BitmapCompressFormatJPEG, options, baos);

}

try {

FileOutputStream fos = new FileOutputStream(file);

foswrite(baostoByteArray());

fosflush();

fosclose();

} catch (Exception e) {

eprintStackTrace();

}

}

这段代码来自Android压缩总结,我根据自己的需求改了改,但是大同小异,所以就直接贴了。

随着代码中的option逐渐变小,我们可以在logcat中打印baos的大小来查看的大小。我们也可以去掉while的循环条件,一直压缩下去看效果,最终一张照片可能就由原来的3、4M变成了几百K甚至几百B了。我在试的过程中将option设置成100,压缩后偶尔会出现一张3、4M的经过压缩后竟变成了6、7M,这里还是有点困惑,不知道为什么。

随后,我想把这个压缩后的(1、200KB)填充到ImageView中时却失败了,logcat中提示过大!这就是文章开头提到的问题,虽然我们通过质量压缩使File形式的文件缩小了,但是并没有改变的宽高,原先是10801920分辨率的经压缩后还是10801920,而File格式转换成Bitmap格式进入到内存中时,内存是根据的像素数量来给分配内存大小的,还是有好几M,因此填充ImageView失败。

顺便提一下,可以用bitmapgetByteCount()获取存储bitmap像素的内存大小,但是KITKAT(Android 44版本)以后用getAllocateByteCount()获取。一般情况下,后者返回值比前者大,比如,当bitmap被重用去decode另外更小的bitmaps时,或者被人为地配置一下属性值,比如setWidth()、setHeight()、reconfigure()时,如果bitmap不做以上 *** 作,二者的返回值应该是一样的。(译文,不太懂)

二、尺寸压缩

特点: 通过设置采样率, 减少的像素, 达到对内存中的Bitmap进行压缩

我们主要通过BitmapFactory中的decodeFile方法对进行尺寸压缩:

public static Bitmap decodeFile (String pathName, BitmapFactoryOptions opts)

public static Bitmap decodeFile (String pathName, BitmapFactoryOptions opts)

其中有两个参数:

pathName是文件的路径。

opts 就是所谓的采样率,它里边有很多属性可以设置,我们通过设置属性来达到根据自己的需要,压缩出指定的。其中比较常用的属性有:

boolean inJustDecodeBounds —— 如果设置为true,则只读取bitmap的宽高,而忽略内容。

int inSampleSize—— 如果>1,调用decodeFile方法后,就会得到一个更小的bitmap对象(已压缩)。比如设置为2,那么新Bitmap的宽高都会是原Bitmap宽高的1/2,总体大小自然就是原来的1/4了,以此类推。

boolean inPurgeable—— 如果设置为true,压缩后的像素占的内存将会在系统清理内存的时候被回收掉,当像素的信息再次被用到时将会自动重新decode该像素(比如getPixels()时)。(慎用!重复decode可以会造成UI的卡顿,API level 21 已弃用)

boolean inInputShareable—— 与inPurgeable配合使用,如果inPurgeable设置成false,自动忽略此值,如果inPurgeable为true,此值决定是否该bitmap能分享引用给输入数据(inputstream,array等),或者必须进行深拷贝。API level 21 已弃用。(这是译文,不太理解!!!)

下面是一段实现的代码

private Bitmap sizeCompres(String path, int rqsW, int rqsH) {

// 用option设置返回的bitmap对象的一些属性参数

final BitmapFactoryOptions options = new BitmapFactoryOptions();

optionsinJustDecodeBounds = true;// 设置仅读取Bitmap的宽高而不读取内容

BitmapFactorydecodeFile(path, options);// 获取到的宽高,放在option里边

final int height = optionsoutHeight;//的高度放在option里的outHeight属性中

final int width = optionsoutWidth;

int inSampleSize = 1;

if (rqsW == 0 || rqsH == 0) {

optionsinSampleSize = 1;

} else if (height > rqsH || width > rqsW) {

final int heightRatio = Mathround((float) height / (float) rqsH);

final int widthRatio = Mathround((float) width / (float) rqsW);

inSampleSize = heightRatio < widthRatio  heightRatio : widthRatio;

optionsinSampleSize = inSampleSize;

}

return BitmapFactorydecodeFile(path, options);// 主要通过option里的inSampleSize对原进行按比例压缩

}

private Bitmap sizeCompres(String path, int rqsW, int rqsH) {

// 用option设置返回的bitmap对象的一些属性参数

final BitmapFactoryOptions options = new BitmapFactoryOptions();

optionsinJustDecodeBounds = true;// 设置仅读取Bitmap的宽高而不读取内容

BitmapFactorydecodeFile(path, options);// 获取到的宽高,放在option里边

final int height = optionsoutHeight;//的高度放在option里的outHeight属性中

final int width = optionsoutWidth;

int inSampleSize = 1;

if (rqsW == 0 || rqsH == 0) {

optionsinSampleSize = 1;

} else if (height > rqsH || width > rqsW) {

final int heightRatio = Mathround((float) height / (float) rqsH);

final int widthRatio = Mathround((float) width / (float) rqsW);

inSampleSize = heightRatio < widthRatio heightRatio : widthRatio;

optionsinSampleSize = inSampleSize;

}

return BitmapFactorydecodeFile(path, options);// 主要通过option里的inSampleSize对原进行按比例压缩

}

上面就是简单的质量压缩与尺寸压缩。

以前在实际项目中使用拍照和从图库中获取时,不知道以何种方式从回调中取得资源,以Bitmap方式还是Uri的形式?如果是使用Bitmap,应该注意些什么,Uri又是一种什么样的格式?有时会出现拍照时回调data数据为空的情况,又该如何定位问题呢?裁剪又是怎样决定方案的?以下将针对这几个问题阐述自己的见解。

在Android中,Intent触发 Camera程序,拍好照片后会返回数据,比如摄像头800万像素,拍出来的尺寸为 3200x2400,占据内存大小=3200 x 2400 x 4bytes / (1024 x 1024) = 30MB 图像设置ARGB_8888一个像素点占据4字节内存,这个尺寸对应的 Bitmap会耗光应用程序的内存,出于安全方面的考虑,Android会给你一个缩略图,比如 160 x 120 px。

Q:为何要返回图缩略?

缩略图是指从onActivityForResullt回调方法中 intent保存的参数。这是因为在启动相机程序拍摄,为了让Bitmap数据能在Activity之间传递,不得不将拍摄后的Bitmap进行压缩再传递,因此通过回调从intent中取得的是缩略图在于拍摄的Bitmap太大,Activity之间Bundle存放的数据不能太大,会导致程序无响应。高清原图是指直接将拍摄的以文件/Uri形式保存到手机。

注:Bitmap实现了Parcelable 接口,所有可以在Activity间使用Intent传递。

Q:使用Bitmap需要注意哪些问题?

1、Android 裁剪 Intent 附加数据的含义

| setExtra | DataType | Desciption | Extra |

|:-------- |:--------:| :------: |

|crop| String | Signals the crop feature | value="true" |

|aspectX|int|Aspect Ratio|裁剪横向比例|

|aspectY|int|Aspect Ratio|裁剪纵向比例|

|outputX|int|width od output created from this intent|输出宽度|

|outputY|int|height od output created from this intent|输出高度|

|scale|boolean|should it scale|是否伸缩|

|return-date|boolean|Return the bitmap with Action-inline-data by using the data|是否返回Bitmap数据|

|data|Parcelable|Bitmap to process, you may provide it a bitmap (not tested)|可设置data为Bitmap或者将相应数据同uri联系起来|

|circleCrop|String|if this string is not null, it will provide some cicular cr||

|MediaStore

EXTRA_OUTPUT("output")|URI|set this URI to a File|输出路径到uri中|

2、裁剪终极方案 — 来源有拍照和图库,可采取的 *** 作有:

3、剪切:

以上就是关于Android加载网络图片,能自动生成缩略图吗全部的内容,包括:Android加载网络图片,能自动生成缩略图吗、Android图片框架对比、android编程:读取指定文件夹下所有png图片等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9808963.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存