分享一个安卓中异步获取网络图片并自适应大小的第三方程序(来自github)
安卓中获取网络图片,生成缓存
用安卓手机,因为手机流量的限制,所以我们在做应用时,要尽量为用户考虑,尽量少耗点用户的流量,而在应用中网络图片的显示无疑是消耗流量最大的,所以我们可以采取压缩图片或者将图片进行缓存,使图片只需要获取一次即可。
获取网络图片,并进行压缩
public static Bitmap returnBitMapWego(String url) {
URL myFileUrl = null;
Bitmap bitmap = null;
try {
myFileUrl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
Options op = new Options();
op.inSampleSize = 2;//压缩的倍数
op.inJustDecodeBounds = false;
Rect rect = new Rect(0, 0, 0, 0);
bitmap = BitmapFactory.decodeStream(is, rect, op);
is.close();
} catch (IOException e) {
// e.printStackTrace();
bitmap = null; }
return bitmap;
}
异步获取网络图片并进行缓存
package com.jijie.yibu; import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.ConnectivityManager;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView; public class LogoLoader { public static final String CACHE_DIR = "/图片在手机中的保存路径";
// 缓存下载过的图片的Map
private Map<String, SoftReference<Bitmap>> caches;
// 任务队列
private List<Task> taskQueue;
private boolean isRunning = false;
private int width, height;
private Context ctx; public LogoLoader(Context ctx) {this.ctx = ctx;
// 初始化变量
caches = new HashMap<String, SoftReference<Bitmap>>();
taskQueue = new ArrayList<LogoLoader.Task>();
// 启动图片下载线程
isRunning = true;
new Thread(runnable).start();
} /**
*
* @param imageView
* 需要延迟加载图片的对象
* @param url
* 图片的URL地址
* @param resId
* 图片加载过程中显示的图片资源
*/
public void showImageAsyn(ImageView imageView, String url, int resId) {
imageView.setTag(url);
Bitmap bitmap = loadImageAsyn(url, getImageCallback(imageView, resId)); if (bitmap == null) {
// imageView.setImageResource(resId);
// imageView.setBackgroundResource(resId);
} else {
// imageView.setImageBitmap(bitmap);
BitmapDrawable bd = new BitmapDrawable(bitmap);
imageView.setBackgroundDrawable(bd);
}
} public Bitmap loadImageAsyn(String path, ImageCallback callback) {
// 判断缓存中是否已经存在该图片
if (caches.containsKey(path)) {
// 取出软引用
SoftReference<Bitmap> rf = caches.get(path);
// 通过软引用,获取图片
Bitmap bitmap = rf.get();
// 如果该图片已经被释放,则将该path对应的键从Map中移除掉
if (bitmap == null) {
caches.remove(path);
} else {
// 如果图片未被释放,直接返回该图片 return bitmap;
}
} else {
// 如果缓存中不常在该图片,则创建图片下载任务
Task task = new Task();
task.path = path;
task.callback = callback; if (!taskQueue.contains(task)) {
taskQueue.add(task);
// 唤醒任务下载队列
synchronized (runnable) {
runnable.notify();
}
}
} // 缓存中没有图片则返回null
return null;
} /**
*
* @param imageView
* @param resId
* 图片加载完成前显示的图片资源ID
* @return
*/
private ImageCallback getImageCallback(final ImageView imageView,
final int resId) {
return new ImageCallback() { public void loadImage(String path, Bitmap bitmap) {
if (path.equals(imageView.getTag().toString())) {
// imageView.setImageBitmap(bitmap);
BitmapDrawable bd = new BitmapDrawable(bitmap);
imageView.setBackgroundDrawable(bd); } else {
// imageView.setImageResource(resId);
// imageView.setBackgroundResource(resId);
}
}
};
} private Handler handler = new Handler() { @Override
public void handleMessage(Message msg) {
// 子线程中返回的下载完成的任务
Task task = (Task) msg.obj;
// 调用callback对象的loadImage方法,并将图片路径和图片回传给adapter
task.callback.loadImage(task.path, task.bitmap);
} }; private Runnable runnable = new Runnable() { public void run() {
while (isRunning) {
// 当队列中还有未处理的任务时,执行下载任务
while (taskQueue.size() > 0) {
// 获取第一个任务,并将之从任务队列中删除
Task task = taskQueue.remove(0);
// 将下载的图片添加到缓存 if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)
&& !checkNetWorkStatus()) {
File file = new File("/mnt/sdcard/jijie/imagecache/"
+ getFileName(task.path));
if (file.exists() && file.length() > 100) { try {
task.bitmap = PicUtil
.getRoundedCornerBitmap(
BitmapFactory
.decodeFile("/mnt/sdcard/jijie/imagecache/"
+ getFileName(task.path)),
10); } catch (OutOfMemoryError err) {
}
}
} else if (checkNetWorkStatus()) { task.bitmap = PicUtil.getRoundedCornerBitmap(
PicUtil.returnBitMap(task.path), 10);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); task.bitmap.compress(Bitmap.CompressFormat.PNG,
100, baos); Write(task.path, baos.toByteArray());
} catch (Exception e) { } } // task.bitmap=PicUtil.getbitmapAndwrite(task.path);
// caches.put(task.path, new
// SoftReference<Bitmap>(task.bitmap));
if (handler != null) {
// 创建消息对象,并将完成的任务添加到消息对象中
Message msg = handler.obtainMessage();
msg.obj = task;
// 发送消息回主线程
handler.sendMessage(msg);
}
} // 如果队列为空,则令线程等待
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}; // 回调接口
public interface ImageCallback {
void loadImage(String path, Bitmap bitmap);
} class Task {
// 下载任务的下载路径
String path;
// 下载的图片
Bitmap bitmap;
// 回调对象
ImageCallback callback; @Override
public boolean equals(Object o) {
Task task = (Task) o;
return task.path.equals(path);
}
} public void Write(String imageurl, byte[] b) {
File cacheFile = FileUtil.getCacheFile(imageurl); BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(cacheFile)); bos.write(b, 0, b.length);
bos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public static String getFileName(String path) {
int index = path.lastIndexOf("/");
return path.substring(index + 1);
} private boolean checkNetWorkStatus() {
boolean netSataus = false;
ConnectivityManager cwjManager = (ConnectivityManager) ctx
.getSystemService(Context.CONNECTIVITY_SERVICE);
cwjManager.getActiveNetworkInfo();
if (cwjManager.getActiveNetworkInfo() != null) {
netSataus = cwjManager.getActiveNetworkInfo().isAvailable();
}
return netSataus;
}
}
经过上面的代码虽然能够实现了图片的异步获取,自动缓存读取,图片压缩的功能,但是处理图片使图片适应控件大小还是比较让人头疼的问题,还有就是如果一起获取大量的网络的图片,会占用的非常多的内存,而且系统默认自由在界面销毁的时候才会释放,所以很容易遇到内存溢出的问题,下面向大家分享一个我在github上看到的一个处理网络的图片的程序。
能够实现异步获取图片,自动缓存读取,自动适应空间大小,而且完美解决内存溢出的问题
下面向大家展示一下:
以集街网(www.jijie.cc)中的一个图片为例,原图为:
<con.standopen.view.NetworkedCacheableImageView
android:id="@+id/nciv_pug"
android:layout_width="fill_parent"
android:layout_height="100dip"
android:scaleType="centerCrop" />
<con.standopen.view.NetworkedCacheableImageView
android:id="@+id/nciv_pug"
android:layout_width="fill_parent"
android:layout_height="300dip"
android:scaleType="centerCrop" />
<con.standopen.view.NetworkedCacheableImageView
android:id="@+id/nciv_pug"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop" />
这分别是在不同大小的空间中显示同一张图片,能够看出来,代码只是将图片进行了剪切处理,避免拉伸变形,程序异步获取和自动缓存就不展示了,大家看代码就行的了。
工程文件(百度网盘):http://pan.baidu.com/s/1mguh2qc
github:https://github.com/yimengqingqiu/Android-Universal-Image-Loader
个人邮箱:standopen@foxmail.com(也可以发邮件给我索取)
分享一个安卓中异步获取网络图片并自适应大小的第三方程序(来自github)的更多相关文章
- php 从一个数组中随机获取固定数据
<?php /* * * 通过一个标识,从一个数组中随机获取固定数据 * $arr 数组 * $num 获取的数量 * $time 随机固定标识值,一般用固定时间或者某个固定整型 * */ fu ...
- react+dva 全局model中异步获取数据state在组件中取不到值
先上结论,不是取不到,是写法有问题. 全文分4部分,1是问题描述,2是一开始的解决想法(错误做法),3是问题产生原因的思考,4是正常解决方法.只想看结论直接跳4 1.问题描述 接触react dva一 ...
- 分享一个JDK批量异步任务工具CompletionService,超好用
摘要:当需要批量提交异步任务,推荐CompletionService.CompletionService将线程池Executor和阻塞队列融合,让批量异步任务管理更简单. 本文分享自华为云社区< ...
- 使用SQL语句从数据库一个表中随机获取数据
-- 随机获取 10 条数据 SQL Server:SELECT TOP 10 * FROM T_USER ORDER BY NEWID() ORACLE:SELECT * FROM (SELECT ...
- 分享一个工作中遇得到的sql(按每天每人统计拖车次数与小修次数)
查询每人每天的数据 首先先建表 CREATE TABLE `user` ( `name` ) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CR ...
- 分享一个js中的bind方法使用
来源:http://www.cnblogs.com/yuzhongwusan/archive/2012/02/13/2348782.html Js代码 复制代码 代码如下: var first_obj ...
- 分享一个vue中的vue-Resource用法
//引入 <script src="//cdn.bootcss.com/vue-resource/1.2.1/vue-resource.js" type="text ...
- 分享一个linux中测试网站是否正常的shell脚本
#! /bin/bash #Author=Harry CheckUrl() { #<==定义函数,名字为CheckUrl timeout=5 #<==定义wget访问的超时时间,超时就退出 ...
- 分享一个Python脚本--统计redis key类型数据大小分布
概述 今天主要介绍怎么统计redis key类型数据大小分布. 原理:使用redis命令: scan.pipline.type 和 debug object 来得到 redis key 信息. 脚本 ...
随机推荐
- 3.6 spring-construction-arg 子元素的使用与解析
对于构造函数子元素是非常常用的. 相信大家也一定不陌生, 举个小例子: public class Animal { public String type; public int age; /** * ...
- codeforces #310 div1 C
操作无论是U还是L,都会使原图形分裂成两个图形,且两个图形的操作互不影响 我们又发现由于操作点只可能在下斜线上,如果将操作按x排序 那么无论是U还是L,都会将操作序列完整分割成两半,且两个操作序列互不 ...
- [itint5]判断是否为二叉搜索树
http://www.itint5.com/oj/#25 这题在leetcode上是用中序遍历来做的,但是这里由于有相等的情况,即左子树小于等于根,这样中序遍历无法完全判定.可以用递归来做,用递归给出 ...
- H264/AVC视频解码时AVC1和H264的区别
AVC1与H264的区别 http://blog.csdn.net/qiuchangyong/article/details/6660253 H.264 Video Types The followi ...
- WinAPI你知道多少?!(上千个,好多都没见过)
http://www.cnblogs.com/vanver/archive/2013/06/13/NO-2013_06_13pm.html 播客开篇,讲讲废话:本篇播客只是推荐给热与钻研的同学们... ...
- 关于 hot code replace fail 问题 .
频频出现Hot code replace failed问题.网上查不到解决方法,想来想去,是否是jvm的问题?我的jre使用自己下载的jdk1.6.07,而MyEclipse的jvm自带的是1.5.0 ...
- CAS SiteMinder (单点登录)
http://www.ibm.com/developerworks/cn/opensource/os-cn-cas/
- Apache Wamp WampServer 配置多端口 多站点 虚拟目录
第一步:配置Apache 的 httpd.conf #Listen 0.0.0.0:80Listen 80Listen 81 第二步:开启虚拟站点 所属文件:httpd.conf #Virtual h ...
- C#中的线程(三) 使用多线程
第三部分:使用多线程 1. 单元模式和Windows Forms 单元模式线程是一个自动线程安全机制, 非常贴近于COM——Microsoft的遗留下的组件对象模型.尽管.NET最大地放弃摆脱了遗留 ...
- MCC(移动国家码)和 MNC(移动网络码)
国际移动用户识别码(IMSI) international mobile subscriber identity 国际上为唯一识别一个移动用户所分配的号码. 从技术上讲,IMSI可以彻底解决国 ...