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

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

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

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. ExtJS4.2学习(五)表格渲染与复选框

    鸣谢:http://www.shuyangyang.com.cn/jishuliangongfang/qianduanjishu/2013-11-10/174.html --------------- ...

  2. BZOJ 3160 万径人踪灭 解题报告

    这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...

  3. API断点大全

    1.限制程序功能函数 EnableMenuItem 允许.禁止或变灰指定的菜单条目EnableWindow 允许或禁止鼠标和键盘控制指定窗口和条目(禁止时菜单变灰) 2.对话框函数 CreateDia ...

  4. zoj 3640 Help Me Escape 概率DP

    记忆化搜索+概率DP 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> #include ...

  5. Redis hash数据类型操作

    Redis hash是一个string类型的field和value的映射表.一个key可对应多个field,一个field对应一个value.将一个对象存储 为hash类型,较于每个字段都存储成str ...

  6. ANDROID_MARS学习笔记_S01_005CheckBox

    一. 1.checkbox_layout.xml <?xml version="1.0" encoding="utf-8"?> <Linear ...

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

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

  8. JavaScript基本程序结构

    条件判断 JavaScript使用if () { ... } else { ... }来进行条件判断.例如,根据年龄显示不同内容,可以用if语句实现如下: var age = 20; if (age ...

  9. 列出man手册所有函数的方法

    locate /man7/|sed -r 's#.*/([^/]+).7.gz$#\1#' locate /man7/ | xargs basename -a -s '.7.gz' apropos - ...

  10. 统计学习方法笔记--EM算法--三硬币例子补充

    本文,意在说明<统计学习方法>第九章EM算法的三硬币例子,公式(9.5-9.6如何而来) 下面是(公式9.5-9.8)的说明, 本人水平有限,怀着分享学习的态度发表此文,欢迎大家批评,交流 ...