安卓中获取网络图片,生成缓存

  用安卓手机,因为手机流量的限制,所以我们在做应用时,要尽量为用户考虑,尽量少耗点用户的流量,而在应用中网络图片的显示无疑是消耗流量最大的,所以我们可以采取压缩图片或者将图片进行缓存,使图片只需要获取一次即可。

获取网络图片,并进行压缩

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)的更多相关文章

  1. php 从一个数组中随机获取固定数据

    <?php /* * * 通过一个标识,从一个数组中随机获取固定数据 * $arr 数组 * $num 获取的数量 * $time 随机固定标识值,一般用固定时间或者某个固定整型 * */ fu ...

  2. react+dva 全局model中异步获取数据state在组件中取不到值

    先上结论,不是取不到,是写法有问题. 全文分4部分,1是问题描述,2是一开始的解决想法(错误做法),3是问题产生原因的思考,4是正常解决方法.只想看结论直接跳4 1.问题描述 接触react dva一 ...

  3. 分享一个JDK批量异步任务工具CompletionService,超好用

    摘要:当需要批量提交异步任务,推荐CompletionService.CompletionService将线程池Executor和阻塞队列融合,让批量异步任务管理更简单. 本文分享自华为云社区< ...

  4. 使用SQL语句从数据库一个表中随机获取数据

    -- 随机获取 10 条数据 SQL Server:SELECT TOP 10 * FROM T_USER ORDER BY NEWID() ORACLE:SELECT * FROM (SELECT ...

  5. 分享一个工作中遇得到的sql(按每天每人统计拖车次数与小修次数)

    查询每人每天的数据 首先先建表 CREATE TABLE `user` ( `name` ) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CR ...

  6. 分享一个js中的bind方法使用

    来源:http://www.cnblogs.com/yuzhongwusan/archive/2012/02/13/2348782.html Js代码 复制代码 代码如下: var first_obj ...

  7. 分享一个vue中的vue-Resource用法

    //引入 <script src="//cdn.bootcss.com/vue-resource/1.2.1/vue-resource.js" type="text ...

  8. 分享一个linux中测试网站是否正常的shell脚本

    #! /bin/bash #Author=Harry CheckUrl() { #<==定义函数,名字为CheckUrl timeout=5 #<==定义wget访问的超时时间,超时就退出 ...

  9. 分享一个Python脚本--统计redis key类型数据大小分布

    概述 今天主要介绍怎么统计redis key类型数据大小分布. 原理:使用redis命令: scan.pipline.type 和 debug object 来得到 redis key 信息. 脚本 ...

随机推荐

  1. What are the advantages of logistic regression over decision trees?FAQ

    What are the advantages of logistic regression over decision trees?FAQ The answer to "Should I ...

  2. HTML可编辑下拉框

    <div style="position:relative;">   <select style="width:120px;" onchang ...

  3. Side-by-side assembly

    Side-by-side technology is a standard for executable files in Windows 98 Second Edition, Windows 200 ...

  4. 1987-A. 集训队选拔

    描述 南邮ACM暑期集训队一年一度的选拔如火如荼的开始了.按照以往的惯例,通过ACM校赛预赛和决赛的两轮选拔,成绩优异者将入选集训队,获得下半年在各大赛区现场赛上与各路神牛角逐奖牌的机会.但是,校赛的 ...

  5. <context:component-scan>配置解析(转)

    在xml配置了这个标签后,spring可以自动去扫描base-pack下和其子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注 ...

  6. [topcoder]BadNeighbors

    http://community.topcoder.com/stat?c=problem_statement&pm=2402&rd=5009 动态规划题.对于圈状的题目有了点感觉. 题 ...

  7. SPRING IN ACTION 第4版笔记-第九章Securing web applications-008-使用非关系型数据库时如何验证用户(自定义UserService)

    一. 1.定义接口 Suppose that you need to authenticate against users in a non-relational database suchas Mo ...

  8. Eclipse中通过Android模拟器调用OpenGL ES2.0函数操作步骤

    原文地址: Eclipse中通过Android模拟器调用OpenGL ES2.0函数操作步骤 - 网络资源是无限的 - 博客频道 - CSDN.NET http://blog.csdn.net/fen ...

  9. 启动C:\Windows\System32\logiLDA.DLL时出现问题,找不到指定模块

    环境:windows8.1专业版 问题:启动C:\Windows\System32\logiLDA.DLL时出现问题,找不到指定模块 每次开机都会弹出上图所示的信息. 经过查找是罗技鼠标驱动的问题:而 ...

  10. Android 使用SDcard进行文件的读取

    平时我们需要在手机上面存储想音频,视频等等的大文件,以前学过使用File进行存储(使用File操作进行存储):由于考虑到手机本身的存储空间小,这时候我们需要把文件存储在SDcard中,今天自己也学习了 ...