Android:下载图像并将其保存为缓存
我有一个从网上下载图片的课程,我需要有人帮我修改下面的代码,以便下载的图片保存在SD卡上。因为我从互联网上获取了这段代码,而且我是一个新手,所以我对为缓存优化这段代码一无所知 我愿意接受任何解决方案。 多谢Android:下载图像并将其保存为缓存,android,Android,我有一个从网上下载图片的课程,我需要有人帮我修改下面的代码,以便下载的图片保存在SD卡上。因为我从互联网上获取了这段代码,而且我是一个新手,所以我对为缓存优化这段代码一无所知 我愿意接受任何解决方案。 多谢 public class ImageThreadLoader { private static final String TAG = "ImageThreadLoader"; // Global cache of images. // Using SoftRefer
public class ImageThreadLoader {
private static final String TAG = "ImageThreadLoader";
// Global cache of images.
// Using SoftReference to allow garbage collector to clean cache if needed
private final HashMap<String, SoftReference<Bitmap>> Cache = new HashMap<String, SoftReference<Bitmap>>();
private final class QueueItem {
public URL url;
public ImageLoadedListener listener;
}
private final ArrayList<QueueItem> Queue = new ArrayList<QueueItem>();
private final Handler handler = new Handler(); // Assumes that this is started from the main (UI) thread
private Thread thread;
private QueueRunner runner = new QueueRunner();;
/** Creates a new instance of the ImageThreadLoader */
public ImageThreadLoader() {
thread = new Thread(runner);
}
/**
* Defines an interface for a callback that will handle
* responses from the thread loader when an image is done
* being loaded.
*/
public interface ImageLoadedListener {
public void imageLoaded(Bitmap imageBitmap );
}
/**
* Provides a Runnable class to handle loading
* the image from the URL and settings the
* ImageView on the UI thread.
*/
private class QueueRunner implements Runnable {
public void run() {
synchronized(this) {
while(Queue.size() > 0) {
final QueueItem item = Queue.remove(0);
// If in the cache, return that copy and be done
if( Cache.containsKey(item.url.toString()) && Cache.get(item.url.toString()) != null) {
// Use a handler to get back onto the UI thread for the update
handler.post(new Runnable() {
public void run() {
if( item.listener != null ) {
// NB: There's a potential race condition here where the cache item could get
// garbage collected between when we post the runnable and it's executed.
// Ideally we would re-run the network load or something.
SoftReference<Bitmap> ref = Cache.get(item.url.toString());
if( ref != null ) {
item.listener.imageLoaded(ref.get());
}
}
}
});
} else {
final Bitmap bmp = readBitmapFromNetwork(item.url);
if( bmp != null ) {
Cache.put(item.url.toString(), new SoftReference<Bitmap>(bmp));
// Use a handler to get back onto the UI thread for the update
handler.post(new Runnable() {
public void run() {
if( item.listener != null ) {
item.listener.imageLoaded(bmp);
}
}
});
}
}
}
}
}
}
/**
* Queues up a URI to load an image from for a given image view.
*
* @param uri The URI source of the image
* @param callback The listener class to call when the image is loaded
* @throws MalformedURLException If the provided uri cannot be parsed
* @return A Bitmap image if the image is in the cache, else null.
*/
public Bitmap loadImage( final String uri, final ImageLoadedListener listener) throws MalformedURLException {
// If it's in the cache, just get it and quit it
if( Cache.containsKey(uri)) {
SoftReference<Bitmap> ref = Cache.get(uri);
if( ref != null ) {
return ref.get();
}
}
QueueItem item = new QueueItem();
item.url = new URL(uri);
item.listener = listener;
Queue.add(item);
// start the thread if needed
if( thread.getState() == State.NEW) {
thread.start();
} else if( thread.getState() == State.TERMINATED) {
thread = new Thread(runner);
thread.start();
}
return null;
}
/**
* Convenience method to retrieve a bitmap image from
* a URL over the network. The built-in methods do
* not seem to work, as they return a FileNotFound
* exception.
*
* Note that this does not perform any threading --
* it blocks the call while retrieving the data.
*
* @param url The URL to read the bitmap from.
* @return A Bitmap image or null if an error occurs.
*/
public static Bitmap readBitmapFromNetwork( URL url ) {
InputStream is = null;
BufferedInputStream bis = null;
Bitmap bmp = null;
try {
URLConnection conn = url.openConnection();
conn.connect();
is = conn.getInputStream();
bis = new BufferedInputStream(is);
bmp = BitmapFactory.decodeStream(bis);
} catch (MalformedURLException e) {
Log.e(TAG, "Bad ad URL", e);
} catch (IOException e) {
Log.e(TAG, "Could not get remote ad image", e);
} finally {
try {
if( is != null )
is.close();
if( bis != null )
bis.close();
} catch (IOException e) {
Log.w(TAG, "Error closing stream.");
}
}
return bmp;
}
}
公共类ImageThreadLoader{
私有静态最终字符串标记=“ImageThreadLoader”;
//图像的全局缓存。
//如果需要,使用SoftReference允许垃圾收集器清理缓存
私有最终HashMap缓存=新HashMap();
私有最终类队列项{
公共网址;
公共ImageLoadedListener;
}
私有最终ArrayList队列=新ArrayList();
private final Handler=new Handler();//假定这是从主(UI)线程启动的
私有线程;
private QueueRunner=new QueueRunner();;
/**创建ImageThreadLoader的新实例*/
公共ImageThreadLoader(){
螺纹=新螺纹(流道);
}
/**
*为将处理的回调定义接口
*完成映像时线程加载程序的响应
*正在加载。
*/
公共接口ImageLoadedListener{
已加载公共无效图像(位图图像位图);
}
/**
*提供可运行类来处理加载
*来自URL的图像和设置
*UI线程上的ImageView。
*/
私有类QueueRunner实现可运行{
公开募捐{
已同步(此){
while(Queue.size()>0){
最终QueueItem项目=队列。删除(0);
//如果在缓存中,请返回该副本并完成
if(Cache.containsKey(item.url.toString())和&Cache.get(item.url.toString())!=null){
//使用处理程序返回更新的UI线程
handler.post(新的Runnable(){
公开募捐{
if(item.listener!=null){
//注意:这里存在缓存项可能获得的潜在竞争条件
//在发布runnable和执行runnable之间收集的垃圾。
//理想情况下,我们将重新运行网络负载或其他。
SoftReference ref=Cache.get(item.url.toString());
如果(ref!=null){
item.listener.imageLoaded(ref.get());
}
}
}
});
}否则{
最终位图bmp=readBitmapFromNetwork(item.url);
如果(bmp!=null){
Cache.put(item.url.toString(),新的SoftReference(bmp));
//使用处理程序返回更新的UI线程
handler.post(新的Runnable(){
公开募捐{
if(item.listener!=null){
item.listener.imageLoaded(bmp);
}
}
});
}
}
}
}
}
}
/**
*为给定图像视图排队以从中加载图像。
*
*@param uri图像的uri源
*@param callback加载映像时要调用的侦听器类
*如果无法分析提供的uri,@将引发MalformedURLException
*@如果图像在缓存中,则返回位图图像,否则返回null。
*/
公共位图loadImage(最终字符串uri,最终ImageLoadedListener侦听器)引发错误的FormedUrlexception{
//如果它在缓存中,就获取它并退出它
if(Cache.containsKey(uri)){
SoftReference ref=Cache.get(uri);
如果(ref!=null){
返回ref.get();
}
}
QueueItem=新的QueueItem();
item.url=新url(uri);
item.listener=监听器;
添加(项目);
//如果需要,启动线程
if(thread.getState()==State.NEW){
thread.start();
}else if(thread.getState()==State.TERMINATED){
螺纹=新螺纹(流道);
thread.start();
}
返回null;
}
/**
*从中检索位图图像的简便方法
*网络上的URL。内置方法
*似乎不起作用,因为他们返回了一个FileNotFound
*例外。
*
*请注意,这不会执行任何线程--
*它在检索数据时阻止调用。
*
*@param url读取位图的url。
*@返回位图图像,如果出现错误,则返回null。
*/
公共静态位图readBitmapFromNetwork(URL){
InputStream=null;
BufferedInputStream bis=null;
位图bmp=null;
试一试{
URLConnection conn=url.openConnection();
连接();
is=conn.getInputStream();
bis=新的BufferedInputStream(is);
bmp=位图工厂.decodeStream(bis);
}捕获(格式错误){
Log.e(标签“坏广告URL”,e);
}捕获(IOE异常){
Log.e(标记“无法获取远程广告图像”,e);
}最后{
试一试{
如果(is!=null)
is.close();
如果(bis!=null)
二、关闭();
}捕获(IOE异常){
Log.w(标记“Err
FileOutputStream os = null;
try {
os = new FileOutputStream(
new File(
android.os.Environment.getExternalStorageDirectory().getAbsolutePath(),
fileName));
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}