`
dyingbleed
  • 浏览: 117368 次
  • 性别: Icon_minigender_1
  • 来自: 东莞
社区版块
存档分类
最新评论

【Android】ListView异步加载远端图片

 
阅读更多

LoadRemoteImage

公有成员方法setRemoteImageListener用于监听远端图片

传入两个参数:String url 图片URL地址  OnRemoteImageListener listener OnRemoteImageListener接口

 

线程Runnable接口处理流程图:

 

 

 

package lizhen.dg;

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

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;

/**
 * 遠端圖片類
 * */
public class LoadRemoteImage {

	private ExecutorService pool; //線程池
	
	private final int MESSAGE_OK = 1; //遠端圖片獲取成功消息
	private final int MESSAGE_ERROR = -1; //遠端圖片獲取錯誤消息
	
	private ImageBuffer imageBuffer; //圖片緩存
	
	
	/**
	 * 構造函數
	 * 執行初始化操作
	 * */
	public LoadRemoteImage() {
		pool = Executors.newCachedThreadPool();
		imageBuffer = new ImageBuffer();
	}
	
	/**
	 * 設置遠端圖片事件監聽器
	 * @param url 圖像URL地址
	 * @param listener 遠端圖片監聽器
	 * */
	public void setRemoteImageListener(final String url, final OnRemoteImageListener listener) {
		
		/*
		 * 遠端圖片消息處理Handler
		 * */
		final Handler handler = new Handler() {

			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				int what = msg.what;
				switch(what) {
				case MESSAGE_OK : //成功 
					listener.onRemoteImage((Bitmap) msg.obj); //調用onRemoteImage回調方法
					break;
				case MESSAGE_ERROR : //錯誤
					listener.onError((String) msg.obj); ////調用onError回調方法
					break;
				}
			}
			
		};
		
		/*
		 * 向線程池中添加新任務
		 * 下載給定URL地址圖片
		 * */
		pool.execute(new Runnable() {
			
			@Override
			public void run() {
				try {
					Bitmap image = null;
					/*
					 * 如果圖片緩存中沒有該圖片,則下載放入緩存中
					 * */
					if((image = imageBuffer.get(url)) == null) {
						byte[] resource = httpRequestByteArray(url); //HTTP請求圖片字節數據
						image = optimizeBitmap(resource, 100, 100); //獲得優化的圖像
						imageBuffer.put(url, image);
					}
					handler.sendMessage(handler.obtainMessage(MESSAGE_OK, image)); //遠端圖像下載成功
				} catch (Exception e) {
					/*
					 * 異常處理
					 * */
					handler.sendMessage(handler.obtainMessage(MESSAGE_ERROR, e.getMessage()));
					return;
				}
			}
		});
	}
	
	/** 
     * 使用HTTP GET方式請求 
     * @param url URL地址 
     * @return HttpEntiry對象 
	 * @throws Exception 
     * */  
    private byte[] httpRequestByteArray(String url) throws Exception {  
        byte[] result = null;  
        HttpGet httpGet = new HttpGet(url);  
        HttpClient httpClient = new DefaultHttpClient();  
        HttpResponse httpResponse;  
        httpResponse = httpClient.execute(httpGet);  
        int httpStatusCode = httpResponse.getStatusLine().getStatusCode();  
        /* 
         * 判斷HTTP狀態碼是否為200 
         * */  
        if(httpStatusCode == HttpStatus.SC_OK) {  
            result = EntityUtils.toByteArray(httpResponse.getEntity());  
        } else {
        	throw new Exception("HTTP: "+httpStatusCode);
        }
        return result;  
    }
	
    private Bitmap optimizeBitmap(byte[] resource, int maxWidth, int maxHeight) {  
        Bitmap result = null;  
        int length = resource.length;  
        BitmapFactory.Options options = new BitmapFactory.Options();      
        options.inJustDecodeBounds = true;  
        result = BitmapFactory.decodeByteArray(resource, 0, length, options);  
        int widthRatio = (int) Math.ceil(options.outWidth / maxWidth);  
        int heightRatio = (int) Math.ceil(options.outHeight / maxHeight);  
        if(widthRatio > 1 || heightRatio > 1) {  
            if(widthRatio > heightRatio) {  
                options.inSampleSize = widthRatio;  
            } else {  
                options.inSampleSize = heightRatio;  
            }  
        }  
        options.inJustDecodeBounds = false;  
        result = BitmapFactory.decodeByteArray(resource, 0, length, options);  
        return result;  
    }
    
    /**
     * 遠端圖片監聽器
     * */
	public interface OnRemoteImageListener {
		
		/**
		 * 遠端圖片處理
		 * @param image 位圖圖片
		 * */
		void onRemoteImage(Bitmap image);
		
		/**
		 * 錯誤處理
		 * @param error 錯誤信息
		 * */
		void onError(String error);
		
	}
	
}

 

ImageBuffer 图片缓存

String键->SoftReference<Bitmap>值储存缓存图片

SoftReference软引用

在内存吃紧抛出“OutOfMemory”异常之前,会被JVM回收,此时调用get方法会返回null

 

 

package lizhen.dg;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

import android.graphics.Bitmap;

/**
 * 圖片緩存類
 * */
public class ImageBuffer {
	
	private Map<String, SoftReference<Bitmap>> buffer = new HashMap<String, SoftReference<Bitmap>>(); //圖片緩存

	/**
	 * 將圖片放進緩存中
	 * @param key 鍵值
	 * @param image Bitmap位圖
	 * */
	public void put(String key, Bitmap image) {
		SoftReference<Bitmap> reference = new SoftReference<Bitmap>(image);
		synchronized(buffer) {
			buffer.put(key, reference);
		}
	}

	/**
	 * 從緩存中取得圖片
	 * @param key 鍵值
	 * @return Bitmap位圖
	 * */
	public Bitmap get(String key) {
		Bitmap result = null;
		synchronized(buffer) {
			if(buffer.containsKey(key)) {
				result = buffer.get(key).get();
			}
		}
		return result;
	}

}

 

ListActivity

ListView列表异步加载远端图片

 

package lizhen.dg;

import android.app.ListActivity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.Toast;

public class Main extends ListActivity {
	
	private String data[] = {
			"http://192.168.211.86/pic/0.jpg"
			, "http://192.168.211.86/pic/1.jpg"
			, "http://192.168.211.86/pic/2.jpg"
			, "http://192.168.211.86/pic/3.jpg"
			, "http://192.168.211.86/pic/4.jpg"
			, "http://192.168.211.86/pic/5.jpg"
			, "http://192.168.211.86/pic/6.jpg"
			, "http://192.168.211.86/pic/7.jpg"
			, "http://192.168.211.86/pic/8.jpg"
			, "http://192.168.211.86/pic/9.jpg"
			, "http://192.168.211.86/pic/10.jpg"
			, "http://192.168.211.86/pic/11.jpg"
			, "http://192.168.211.86/pic/12.jpg" //錯誤的圖片地址
			};
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        setListAdapter(new MyListAdapter(this, data));
    }
    
    private class MyListAdapter extends BaseAdapter {
    	
    	private Context context;
    	private String[] data;
    	private LoadRemoteImage remoteImage;
    	
    	public MyListAdapter(Context context, String[] data) {
    		this.context = context;
    		this.data = data;
    		remoteImage = new LoadRemoteImage();
    	}

		@Override
		public int getCount() {
			return data.length;
		}

		@Override
		public Object getItem(int position) {
			return data[position];
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			Holder holder = null;  
            if(convertView == null) {  
                convertView = getLayoutInflater().inflate(R.layout.item, parent, false);  
                holder = new Holder(convertView);  
                convertView.setTag(holder);  
            } else {  
                holder = (Holder) convertView.getTag();  
            }
            final ImageView icon = holder.getIcon();
            icon.setImageResource(R.drawable.icon);
            remoteImage.setRemoteImageListener((String) getItem(position), new LoadRemoteImage.OnRemoteImageListener() {
				
				@Override
				public void onError(String error) {
					Toast.makeText(context, error, Toast.LENGTH_LONG).show();
				}

				@Override
				public void onRemoteImage(Bitmap image) {
					icon.setImageBitmap(image);
				}
			});
            holder.getName().setText((String) getItem(position));  
            return convertView;  
		}
    	
    }
    
}

 

package lizhen.dg;

import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class Holder {
	private View parentView;  
    private ImageView iconImageView;  
    private TextView labelTextView;  
      
    public Holder(View view) {  
        this.parentView = view;  
    }  
      
    public ImageView getIcon() {  
        if(iconImageView == null) {  
            iconImageView = (ImageView) parentView.findViewById(R.id.item_IconImageView);  
        }  
        return iconImageView;  
    }  
      
    public TextView getName() {  
        if(labelTextView == null) {  
            labelTextView = (TextView) parentView.findViewById(R.id.item_NameTextView);  
        }  
        return labelTextView;  
    }  
}
 

运行结果:

 

  • 大小: 28.2 KB
  • 大小: 90.9 KB
分享到:
评论

相关推荐

    android listView 异步加载图片

    这里的“android listView 异步加载图片”指的是在不阻塞UI线程的情况下,从网络、本地存储或其他来源加载图片到ListView中的技术。 这篇名为“ImageLoader”的Java文件很可能就是一个实现图片异步加载的工具类。在...

    Android ListView异步加载图片

    Android 异步加载图片,对ListView的异步加载图片的功能演示,主要根据url读取图片返回流的方法。为了方便演示,将请求图片的链接先固定,每读取好一个图片就更新,界面比较简单,当然你可以做成比较好的,像很多好...

    Android Listview异步加载图片

    本文将深入探讨Android ListView中异步加载图片的策略、常见问题以及解决方案。 首先,我们要理解异步加载的基本原理。异步加载是指在后台线程中执行耗时操作,如加载图片,而主线程则继续处理用户交互,保证界面...

    Android实现ListView异步加载图片

    "Android实现ListView异步加载图片" Android 实现 ListView 异步加载图片是一种常见的技术,旨在提高应用程序的性能和用户体验。本文将详细介绍 Android 中实现 ListView 异步加载图片的方法,并对相关的技术概念...

    android listview异步加载图片实例(线程池+数据库+本地保存)

    本实例将详细讲解如何实现“Android ListView异步加载图片”,结合线程池、数据库和本地保存来优化性能。 首先,我们需要理解异步加载的概念。在Android中,由于主线程负责用户界面的更新,因此不应在主线程中执行...

    android listView图片异步加载(拖动时不加载,双缓存)

    通过以上步骤,我们可以实现一个高效的图片异步加载方案,确保ListView在滚动时保持流畅,同时充分利用双缓存策略降低网络请求频率,提升应用性能。在实际项目中,可以根据需求选择合适的第三方库,或者自定义实现以...

    ListView异步加载图片

    为了解决这个问题,我们需要实现ListView的异步加载图片功能。本篇文章将详细介绍如何通过软引用缓存图片,实现高效、流畅的异步加载机制。 一、异步加载原理 异步加载的基本思想是将耗时的操作(如网络请求和图片...

    listview 异步加载网络图片

    在ListView中使用Glide,可以在Adapter的getView方法中调用Glide.with(context).load(url).into(imageView)来加载图片。Glide会自动管理图片的生命周期,防止内存泄漏。 4. **缓存机制**:异步加载的同时,利用本地...

    android ListView异步加载图片示例

    这个“android ListView异步加载图片示例”就是为了解决这个问题。 首先,我们要理解ListView的机制。ListView通过复用视图(convertView)来提高性能,即只有当前屏幕可见的几项会创建View,其余的View会在滚动时...

    Android中ListView全面完美的网络图片的异步加载

    "Android中ListView全面完美的网络图片异步加载"这一主题正是解决这些问题的关键。 首先,我们需要理解异步加载的概念。异步加载意味着在后台线程处理耗时操作,如下载和解码图片,而不是在主线程中执行,这样可以...

    android listview 异步加载图片并防止错位

    "android listview 异步加载图片并防止错位"这个主题就是针对这些问题提出的一种解决方案。 异步加载图片是为了避免在主线程中执行耗时操作,导致UI卡顿。通常,我们使用异步任务(如AsyncTask)或者专门的图片加载...

    listview异步加载.rar

    ListView是Android平台上常见的一种用于展示大量数据的视图组件,尤其在处理长列表时,它的异步加载机制显得尤为重要。异步加载是为了提高用户体验,避免因加载大量数据而导致UI线程阻塞,使得应用程序响应变慢甚至...

    Android ListView 异步加载图片

    在Android开发中,ListView是展示大量...通过以上策略,我们可以实现高效的Android ListView图片异步加载,提高应用的性能和用户体验。记得在编码过程中,注意代码的可读性和可维护性,遵循最佳实践,避免潜在的问题。

    AystnPicture_Android ListView异步加载图片.rar

    "AystnPicture_Android ListView异步加载图片.rar"这个压缩包文件很可能是提供了一种解决方案,即异步加载图片到ListView中,以提高用户体验。 异步加载图片的主要目的是避免阻塞主线程,主线程负责处理用户交互和...

    Android实现Listview异步加载网络图片并动态更新的方法

    本文实例讲述了Android实现Listview异步加载网络图片并动态更新的方法。分享给大家供大家参考,具体如下: 应用实例:解析后台返回的数据,把每条都显示在ListView中,包括活动图片、店名、活动详情、地址、电话和...

    ListView异步加载图片进度条

    综上所述,实现ListView中的异步加载图片进度条,需要综合运用多线程、图片缓存、UI更新等技术,并遵循良好的代码组织和错误处理原则。通过合理的封装和接口设计,可以使得代码更加规范,同时也提升了用户体验。

    android ListView异步加载图片和优化

    本篇将深入探讨如何在Android ListView中实现异步加载图片以及相关的优化策略。 1. **异步加载图片**:在ListView中,由于滚动频繁,直接同步加载网络图片会阻塞主线程,导致界面卡顿。为了解决这个问题,可以使用...

Global site tag (gtag.js) - Google Analytics