`
zhuixinjian
  • 浏览: 66734 次
  • 性别: Icon_minigender_1
  • 来自: 湖北人在北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

异步加载图片

阅读更多

前几天记得说要分享一下异步下载加载图片的经验,最近一直在研究Cocos2d,把这事耽误了。今天就写了写 

 

如果不怕图片那个内存溢出的bug的话。可以使用ListView,GridView等等,如果担心这个问题,可以使用ImageView

 

既然是异步加载,那就采用多线程下载吧。 这个例子里面也就用了一个线程池

 

1.

//初始化线程池

ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 3,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());

 

2.

    //构建一个ListView

listView = (ListView) findViewById(R.id.listview);

 

3.

   //启动一个下载列表的线程

threadPool.execute(new LoadImagesListThread());

 

4.

        /**
	 * 下载图片列表的线程
	 * @author zhu
	 *
	 */
	class LoadImagesListThread extends Thread{
		@Override
		public void run() {

			//TODO 获取下载图片列表的
			datas = HttpUtils.LoadImagesList(); 

			if(datas != null && datas.size()>0){
				
				//通知显示列表
				handler.sendEmptyMessage(SHOW_IMAGES);
				
				//循环启动线程下载图片
				for (int i = 0; i < datas.size(); i++) {
					threadPool.execute(new LoadImageThread());
				}
			}else{
				//TODO 通知没有数据
				handler.sendEmptyMessage(NO_IMAGES);
			}
		}
		
	}

5.

下载图片的线程如下,很简单

	class LoadImageThread extends Thread{
		
		int position;
		
		public LoadImageThread(int position){
			this.position = position;
		}
		
		@Override
		public void run() {
			//TODO 下载图片。这个下载方法里面可以先判断是否本地缓存有,如果有,就读缓存。没有就下载,再写缓存
			datas.get(position).bitmap = HttpUtils.loadImage(datas.get(position).url);
			handler.sendEmptyMessage(SHOW_IMAGE);
		}
		
	}

6.

handler里面主要做些刷新的工作

	Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case SHOW_IMAGES:
				adapter = new MyAdapter();
				listView.setAdapter(adapter);
				break;
			case NO_IMAGES:
				Toast.makeText(MainActivity.this, "no images", Toast.LENGTH_LONG).show();
				break;
			case SHOW_IMAGE:
				adapter.notifyDataSetChanged();
				break;
			default:
				break;
			}
			
		};
	};
 

 

至此一个简单的异步加载图片的功能完成了。

 

图片太多。使用ListView,GridView的时候会报内存溢出的错误,我的经验是320x480大小的12张左右必报。坛子里也讨论了许久,没有结果,都是缩放图片或者避开这个大量图片的问题。我就采用的是避开大量图片的方法。过几天再写出来

 

 

 

分享到:
评论
10 楼 hibernater 2010-09-02  
转化成小图,大图recycle掉也可以
9 楼 zuo_huai 2010-08-29  
我也发现了内存溢出的情况,请要怎么去处理呀!
8 楼 aa87963014 2010-08-25  
圈子加了是加了。但是好像不是很活跃。

坛子?圈子? 还是 q q 群?
7 楼 luodaijun 2010-08-24  
IO操作工具类,其实是包装了apache commons-io

package com.zbkc.mamclient.util;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
* Created by IntelliJ IDEA.
* User: 罗代均
* Date: 2010-8-23
* Time: 0:17:32
*/
public class IOUtilsEx extends IOUtils {

    /**
     * 拷贝URL内容到输出流
     *
     * @param srcUrl
     */
    public static void copyUrl(String srcUrl, OutputStream destOutpstream) {
        InputStream is = null;
        HttpEntity entity = null;
        HttpClient client = null;
        try {
            client = new DefaultHttpClient();
            HttpGet get = new HttpGet(srcUrl);
            HttpResponse response = client.execute(get);
            entity = response.getEntity();
            is = entity.getContent();
            copy(is, destOutpstream);
        } catch (IOException ex) {

        } finally {
            if (entity != null) {
                try {
                    entity.consumeContent();
                } catch (IOException e) {

                }
            }
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(destOutpstream);
        }
    }
}
6 楼 luodaijun 2010-08-24  
aa87963014 写道
ls 和我的做法一样 保存到本地。

File dir = cacheFile.getParentFile();
        if (!dir.exists()) {
            dir.mkdirs();
        }

这个判断 我那到其他地方去了,就不用每次都判断一次。

ThreadPoolFactory 线程池? 我对这个不太熟悉 有什么特别的好处吗?

你是怎么实现的?

还有 我的 imageView 在listView里面 下载完之后 还要更新视图 感觉有点怪怪的。
不知道 有没什么好的方法


这个判断性能影响有限,主要是为了这个控件更加健壮,线程池用Java自带的
package com.zbkc.mamclient.util;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Created by IntelliJ IDEA.
* User: 罗代均
* Date: 2010-8-5
* Time: 21:14:02
* 线程池
*/
public class ThreadPoolFactory {
    private static ThreadPoolFactory ourInstance = new ThreadPoolFactory();

    public static ThreadPoolFactory getInstance() {
        return ourInstance;
    }

    private ExecutorService threadPool;

    private ThreadPoolFactory() {
        threadPool = Executors.newCachedThreadPool();
    }


    /**
     * 提交给线程池执行
     *
     * @param run
     */
    public void execute(Runnable run) {
        threadPool.submit(run);
    }
}


5 楼 zhuixinjian 2010-08-24  
学android居然没有加入组织。落后了啊

搜索下hong老大的坛子。
4 楼 aa87963014 2010-08-24  
ls 和我的做法一样 保存到本地。

File dir = cacheFile.getParentFile();
        if (!dir.exists()) {
            dir.mkdirs();
        }

这个判断 我那到其他地方去了,就不用每次都判断一次。

ThreadPoolFactory 线程池? 我对这个不太熟悉 有什么特别的好处吗?

你是怎么实现的?

还有 我的 imageView 在listView里面 下载完之后 还要更新视图 感觉有点怪怪的。
不知道 有没什么好的方法
3 楼 luodaijun 2010-08-24  
package com.zbkc.mamclient.ui.common;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
import com.zbkc.mamclient.util.IOUtilsEx;
import com.zbkc.mamclient.util.ThreadPoolFactory;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;


/**
* Created by IntelliJ IDEA.
* User: 罗代均
* Date: 2010-8-23
* Time: 1:05:37
*/
public class WebImageView extends ImageView {

    private final static String TAG = WebImageView.class.getName();

    private Handler handler = new Handler();

    public WebImageView(Context context) {
        super(context);
    }

    public WebImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public WebImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * @param url       图片的URL地址
     * @param cacheFile 图片第一次下载后,存到本地文件,下次不用网络下载
     */
    public void setImageUrl(final String url, final File cacheFile) {

        Log.d(TAG, "load image,url:" + url + ",cacheFile:" + cacheFile.getAbsolutePath());

        File dir = cacheFile.getParentFile();
        if (!dir.exists()) {
            dir.mkdirs();
        }

        if (cacheFile.exists()) {
            setImageBitmap(BitmapFactory.decodeFile(cacheFile.getAbsolutePath()));
            return;
        }

        ThreadPoolFactory.getInstance().execute(new Runnable() {
            public void run() {
                try {
                    IOUtilsEx.copyUrl(url, new FileOutputStream(cacheFile));

                    handler.post(new Runnable() {
                        public void run() {
                            setImageBitmap(BitmapFactory.decodeFile(cacheFile.getAbsolutePath()));
                        }
                    });
                } catch (Exception e) {
                    Log.e(TAG, "setImageUrl error", e);
                }

            }
        });
    }


    public void setImageUrl(final String url) {
        Log.d(TAG, "load image,url:" + url);

        ThreadPoolFactory.getInstance().execute(new Runnable() {
            public void run() {
                InputStream is = null;
                try {
                    is = new URL(url).openStream();
                    final Bitmap bmp = BitmapFactory.decodeStream(is);
                    handler.post(new Runnable() {
                        public void run() {
                            setImageBitmap(bmp);
                        }
                    });
                } catch (Exception e) {
                    Log.e(TAG, "setImageUrl error", e);
                } finally {
                    IOUtils.closeQuietly(is);
                }

            }
        });
    }
}
2 楼 aa87963014 2010-08-24  
你是在哪讨论的?
1 楼 zhs2472 2010-08-21  
不错  很简练  学习了  期待有更精彩的深入研究

相关推荐

    wpf 异步加载图片完成后再显示

    在WPF(Windows Presentation Foundation)应用开发中,异步加载图片是提高用户体验的关键技术,特别是在处理大尺寸或者网络延迟较大的情况下。本知识点将详细讲解如何实现wpf异步加载图片并在加载完成后显示。 ...

    lazyload异步加载图片

    **懒加载(Lazy Load)异步加载图片技术详解** 懒加载是一种优化网页性能的技术,它主要应用于图片或者视频等大体积资源的加载。在网页初次加载时,只加载视口内的图片,当用户滚动页面,即将进入视口的图片才会被...

    Android异步加载图片例子

    在Android开发中,异步加载图片是一项至关重要的技术,尤其对于那些包含大量图像的移动应用而言,如社交网络、电商应用等。异步加载能够提高用户体验,避免UI线程阻塞,防止应用出现"卡死"现象。在这个"Android异步...

    Android AsyncTask用法和异步加载图片.rar

    本资料包主要讲解了如何使用`AsyncTask`进行异步加载图片,这对于在UI线程中保持流畅用户体验至关重要。 `AsyncTask`是Android SDK中的一个类,它为开发者提供了简单的多线程和回调功能。它的核心思想是将长时间...

    JS异步加载图片

    在JavaScript(JS)中,异步加载图片是一种优化网页性能的技术。它允许浏览器在不影响页面主要功能的情况下,按需或后台加载非关键资源,如图片。这样可以减少页面初次加载的时间,提高用户体验,特别是对于含有大量...

    使用Android Studio 练习RecyclerView 异步加载图片,解决图片乱序问题。

    然而,在实际开发中,当我们需要在RecyclerView中异步加载图片时,可能会遇到图片显示乱序的问题。本文将深入探讨这个问题及其解决方案。 首先,我们来理解为什么会出现图片乱序的现象。这是因为RecyclerView在滚动...

    iOS异步加载图片 (需要至少12个字的名称,过分!)

    在iOS开发中,异步加载图片是一项至关重要的技术,它能显著提升应用的性能和用户体验。标题中的"iOS异步加载图片"暗示我们讨论的是如何在iOS应用中避免UI阻塞,通过后台线程加载图片资源,使得界面始终保持流畅。在...

    ListView异步加载图片

    为了解决这个问题,我们需要采用异步加载图片的策略。这就是“ListView异步加载图片”这一知识点的核心。 异步加载图片的目的是将耗时的操作(如网络请求、图片解码)从主线程分离到后台线程执行,从而保持用户界面...

    iphone UITableView异步加载图片

    因此,"iPhone UITableView异步加载图片"是解决这个问题的关键技术。 异步加载图片的基本思想是在主线程之外的其他线程(通常为后台线程)下载和处理图片,避免阻塞用户界面。在UITableView中,我们通常会在cell...

    Android实现ListView异步加载图片

    本篇文章将深入探讨如何在Android中实现ListView异步加载图片,主要涉及以下几个关键知识点: 1. **AsyncTask**:Android提供了AsyncTask类,用于在后台线程执行耗时操作,并在UI线程更新结果。在图片加载场景中,...

    网络异步加载图片的轮播图带点击方法

    在IT行业中,网络异步加载图片的轮播图是一种常见的用户界面组件,广泛应用于网站、APP等场景,用于展示多张图片并实现自动或手动切换。在这个特定的【标题】"网络异步加载图片的轮播图带点击方法"中,我们可以深入...

    iOS从网络异步加载图片

    接下来,我们讨论核心主题——异步加载图片。在iOS应用中,直接在主线程上加载网络图片会阻塞用户界面,导致应用程序响应变慢,影响用户体验。因此,异步加载成为最佳实践。IconDownloader是一个用于异步下载和缓存...

    以AJAX方式加载图片=异步加载图片,先显示个图片的占位图片 此技术常见于漫画网站.zip

    在网页开发中,异步加载图片(以AJAX方式加载图片)是一种常见的优化技术,尤其在处理大量图片的场景下,比如漫画网站。通过这种方式,可以显著提高页面加载速度,提升用户体验。AJAX(Asynchronous JavaScript and ...

    Android用AsyncTask异步加载图片(新)

    在Android应用开发中,异步加载图片是一项常见的需求,特别是在处理大数据量的图像时,如在GridView或ListView中展示图片。`AsyncTask`是Android提供的一种轻量级的多线程解决方案,它允许开发者在后台执行耗时操作...

    Android 演示异步加载图片的实现 附源代码.rar

    Android 演示异步加载图片的实现 附源代码,这里主要是演示ListView的异步加载图片功能,异步加载一个view时,如果view里面有EditText,EditText在每次加载view都会触发焦点,这时候异步就会出错。可能我这样说不太...

    Android 异步加载图片实现_图片缓存.zip

    在Android应用开发中,异步加载图片是一项至关重要的任务,特别是在处理大量图片或者网络图片时。这不仅可以提高用户体验,避免因加载图片导致的界面卡顿,还能有效地节省系统资源。本教程将深入探讨如何在Android中...

    ListView异步加载图片进度条

    在处理大量图片时,为了提升用户体验和优化性能,通常会采用异步加载图片的技术。本文将深入探讨如何实现ListView中图片的异步加载,并结合进度条显示加载状态,使代码更加规范。 一、异步加载图片的重要性 在...

    android异步加载图片

    "Android异步加载图片"是一个常见的需求,它涉及到用户体验优化、内存管理以及线程安全等多个方面。这里我们将深入探讨这个主题,并结合提供的"ImageLoader-develop"可能是一个图片加载库的源码,来讲解相关的知识点...

    Android中实现异步加载图片的Demo

    在Android开发中,异步加载图片是一项至关重要的技术,它能显著提升用户体验,尤其是在处理大量图片数据时。这个"Android中实现异步加载图片的Demo"展示了如何在Android应用中高效地加载和显示图片,无论是从本地...

Global site tag (gtag.js) - Google Analytics