ListView中使用ImageLoader框架下载网络图片显示

首先,ListView中如何下载文字和图片,大家可以看看本人之前的blog
ListView获取网络数据显示

所以这里关于首次如何下载xml数据,绑定适配器等就不更详细有了,主要是分享如何在ListView中使用ImageLoader这个开源框架如下载图片。

首先介绍一下ImageLoader。用户在快速拖动的时候容易出现卡顿的现象,可能下载不及时完全,然后有时候会可能出现显示错误的item的ImageView等问题,使用开源框架ImageLoader就可以较好的控制这个问题。

首先,使用ImageLoader需要注意的地方,大家可以去看一片blog:http://blog.csdn.net/liweijie_chengxuyuan/article/details/45222167

首先,我们先去配置Application

他的代码如下:需要把他设置在清单文件中,作为application的name属性的值,注意假如该类不再项目包底下,设置需要加上他的完整包路径+类名

import java.io.File;
import android.app.Application;
import android.content.Context;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.utils.StorageUtils;
public class MyApplication extends Application
{
	@Override
	public void onCreate()
	{
		super.onCreate();
		initImageLoader(getApplicationContext());
	}
	public static void initImageLoader(Context context)
	{
		File cache = StorageUtils.getOwnCacheDirectory(context,"liweijie/cache");
		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
		.threadPriority(Thread.NORM_PRIORITY - 2) //设置ImageLoader的线程的优先级
		.threadPoolSize(3) //设置他的线程池的最大数量 推荐1- 5 个,预防OOM,不要设置成太大
		.discCache(new UnlimitedDiscCache(cache)) //设置文件缓存到SD卡或者手机的位置
		.denyCacheImageMultipleSizesInMemory() // 设置
		.discCacheFileNameGenerator(new Md5FileNameGenerator()) // 图片的编码方式MD5编码
		.tasksProcessingOrder(QueueProcessingType.LIFO) //默认的
		.writeDebugLogs()
		.build();
		ImageLoader.getInstance().init(config); //初始化ImageLoader的配置,必须
	}
}

ImageLoader采用单例设计模式,ImageLoader imageLoader = ImageLoader.getInstance();得到该对象,每个ImageLoader采用单例设计模式,ImageLoader必须调用init()方法完成初始化。

使用的时候这两点是需要注意的,一个是在Application中intiImageLoader,在清单文件中加入访问网络权限。

然后对于图片的各种设置可以通过DisplayImageOptions 来设置,根据自己的需求进行设置就好。

isplayImageOptions options;
options = new DisplayImageOptions.Builder()
 .showImageOnLoading(R.drawable.ic_launcher) //设置图片在下载期间显示的图片
 .showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher)  //设置图片加载/解码过程中错误时候显示的图片
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
.cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true)  //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//
.decodingOptions(android.graphics.BitmapFactory.Options decodingOptions)//设置图片的解码配置
//.delayBeforeLoading(int delayInMillis)//int delayInMillis为你设置的下载前的延迟时间
//设置图片加入缓存前,对bitmap进行设置
//.preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
.displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
.displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间
.build();//构建完成   

在adapter中下载图片的时候使用到的ImageLoader的方法是displayImage()和loadImage()这两个方法。本篇blog使用displayImage()方法,他比较简单好用。

下载是本demo的详细:

大概项目框架:

MainActivity的代码:他的作用是初始化图片的配置,如上面的DisplayImageOptions ,他是继承于BaseActivity(下面讲),然后他是会开一条线程下载在服务器的xml数据,包含显示的文字和图片的URL,通过使用Handler机制来绑定适配器,一下载数据完全就绑定适配器,适配器运行于UI线程,它里面包含一个ImageLoader对象负责下载对应的image显示出来。

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Window;
import android.widget.ListView;
import android.widget.Toast;
import com.example.myimageloader.domain.News;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;

public class MainActivity extends BaseActivity
{
	private DisplayImageOptions options;
	private ListView listview;
	private List<News> datas = new ArrayList<News>();
	private Handler mHandler = new Handler()
	{
		public void handleMessage(android.os.Message msg)
		{
			if (msg.what == 1)
			{
				System.out.println(((List<News>) msg.obj).size());
				listview.setAdapter(new MyListAdapter((List<News>) msg.obj, MainActivity.this, imageLoader, options));
			}
			else if (msg.what == -1)
			{
				Toast.makeText(getApplicationContext(), "网络有问题", Toast.LENGTH_SHORT).show();
			}
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		listview = (ListView) this.findViewById(R.id.myListView);
		options = new DisplayImageOptions.Builder().showStubImage(R.drawable.ic_launcher) // 设置图片没有下载完全之前显示的图片
				.showImageForEmptyUri(R.drawable.ic_empty) // 设置URL为空的时候或者是错误的时候显示的图片
				.showImageOnFail(R.drawable.ic_error) // 设置图片加载或者是解码错误过程中显示的图片
				.cacheInMemory(true) // 设置可以缓存在内存中
				.cacheOnDisc(true) // 设置可以缓存在SD卡或者手机上
				.displayer(new RoundedBitmapDisplayer(20)) // 设置为圆角图片
				.build();// 创建配置过得DisplayImageOption对象

		new MyThredLoadNews(datas, mHandler).start();
	}
}

final class MyThredLoadNews extends Thread
{
	private List<News> datas;
	private Handler handler;

	public MyThredLoadNews (List<News> datas , Handler handler)
	{
		this.datas = datas;
		this.handler = handler;
	}

	@Override
	public void run()
	{
		try
		{
			datas.addAll(NewsService.getData());
			System.out.println(NewsService.getData().size());
			Message msg = Message.obtain();
			msg.what = 1;
			msg.obj = datas;
			handler.sendMessage(msg);
		} catch (IOException e)
		{
			handler.sendEmptyMessage(-1);
			e.printStackTrace();
		} catch (Exception e)
		{
			handler.sendEmptyMessage(-1);
			e.printStackTrace();
		}
	}
}

BaseActivity的作用是处理菜单,假如有的手机没有菜单键他点击ActionBar的时候会弹出来,有菜单键则会自动弹出,有两个菜单,一个是清除内存缓存,一个是清除手机本地缓存。并且负责实例化ImageLoader被MainActivity继承,他没有界面,不想要在清单文件声明。

public class BaseActivity extends Activity
{
	protected ImageLoader imageLoader = ImageLoader.getInstance();

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch (item.getItemId())
		{
		case R.id.item_clear_memory_cache:
			imageLoader.clearMemoryCache();
			return true;
		case R.id.item_clear_disc_cache:
			imageLoader.clearDiskCache();
			return true;
		default:
			return false;
		}
	}
}

Service类,负责下载和解析xml数据的一个

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
import com.example.myimageloader.domain.News;
public class NewsService
{
         //下载xml数据
	public static List<News> getData() throws Exception, IOException
	{
		String path = "http://192.168.1.109:8080/web/mylist1.xml";
		HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
		conn.setConnectTimeout(5000);
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		if (200 == conn.getResponseCode())
		{
			InputStream stream = conn.getInputStream();
			return parserXML(stream);
		}
		return null;
	}
<span style="white-space:pre">	</span>//解析xml数据
	private static List<News> parserXML(InputStream stream) throws Exception
	{
		List<News> datas = new ArrayList<News>();
		News news = null;
		XmlPullParser parser = Xml.newPullParser();
		parser.setInput(stream, "UTF-8");
		int event = parser.getEventType();
		while (event != XmlPullParser.END_DOCUMENT)
		{
			switch (event)
			{
			case XmlPullParser.START_TAG:
				if ("image".equals(parser.getName()))
				{
					news = new News();
					news.name = parser.getAttributeValue(0);
					break;
				}
				if ("path".equals(parser.getName()))
				{
					news.path = parser.nextText();
					break;
				}
				break;

			case XmlPullParser.END_TAG:
				if ("image".equals(parser.getName()))
				{
					datas.add(news);
					news = null;
					break;
				}
				break;
			}
			event = parser.next();
		}
		return datas;
	}

}

adapter类,他的作用就是联系数据和listview,然后启用ImageLoader下载对应item的图片

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.myimageloader.domain.News;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;

public class MyListAdapter extends BaseAdapter
{
	private ImageLoadingListener listener = new FirstDisplatListener();
	private List<News> datas = new ArrayList<News>();
	private LayoutInflater inflater;
	private ImageLoader imageLoader;
	private DisplayImageOptions options;
	public MyListAdapter (List<News> datas , Context context,ImageLoader imageLoader,DisplayImageOptions options)
	{
		this.datas.addAll(datas);
		inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		this.imageLoader = imageLoader;
		this.options = options;
		System.out.println("ok111");
		System.out.println(this.datas.size());
	}

	@Override
	public int getCount()
	{
		return datas.size();
	}

	@Override
	public Object getItem(int position)
	{
		return datas.get(position);
	}

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

	@Override
	public View getView(int position, View convertView, ViewGroup parent)
	{
		ViewHolder holder = null;
		if (null == convertView)
		{
			holder = new ViewHolder();
			convertView = inflater.inflate(R.layout.list_item, null);
			holder.imageView = (ImageView) convertView.findViewById(R.id.image);
			holder.textView = (TextView) convertView.findViewById(R.id.text);
			convertView.setTag(holder);
		} else
		{
			holder = (ViewHolder) convertView.getTag();
		}
		System.out.println("okliweijie");
		News news = datas.get(position);
		holder.textView.setText(news.name +"+item " + (position + 1));
		imageLoader.displayImage(news.path, holder.imageView, options, listener);
		return convertView;
	}

	private class ViewHolder
	{
		public TextView textView;
		public ImageView imageView;
	}

	private static class FirstDisplatListener extends SimpleImageLoadingListener
	{
		static final List<String> diaplayImages = Collections.synchronizedList(new LinkedList<String>());

		@Override
		public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage)
		{
			if (loadedImage == null)
			{
				ImageView imageView = (ImageView) view;
				boolean firstDisplay = !diaplayImages.contains(imageUri);
				if (firstDisplay)// 不存在的时候,这时候是属于第一次显示,使用一个渐变的动画,然后把该uri对应的imageview存放到list中
				{
					FadeInBitmapDisplayer.animate(imageView, 500);
					diaplayImages.add(imageUri);
				}
			}
		}
	}
}

Application类,配置ImageLoader,在上面第一个。其中News这个类是包含name和path两个属性就不贴代码出来了。结果截图

时间: 2024-10-08 02:55:09

ListView中使用ImageLoader框架下载网络图片显示的相关文章

listview中getview异步加载网络图片

前言:本以为异步加载挺简单,因为网上代码多,但真想要做好,还真不那么简单,从看代码到弄懂再到自己写,实在是有太多的东西需要学了,用了两天的时间,终于弄出来了,因为用到回调函数,所以理解起来可能难度有点大,讲起来也不太好讲,我尽力讲的明白些,其实还是要多看代码,自己摸索摸索,动手写写就什么都理解了.这篇我们只讲怎样实现异步加载,对于滑动时停止加载的事下篇再讲. 实现效果: 1.异步加载图片,在加载图片时,先加载一个默认的图片,然后在后台加载图片,加载完成后显示出来: 2.当用户在滑动时,停止加载图

第四天 下载网络图片显示

访问网络需要权限  <uses-permission android:name="android.permission.INTERNET"/> 1. 要请求的图片地址  String imgurl ="http://pic12.nipic.com/20110112/4775714_091244001112_2.jpg"; 2. 获取URL对象   URL url = new URL(imgurl); 3.获取服务器连接对象     HttpURLConn

C#中使用aria2c进行下载并显示进度条

正则表达式的生成网站: http://www.txt2re.com/index-csharp.php3 Program.cs static void Main(string[] args) { var url = "https://download.microsoft.com/download/E/4/1/E4173890-A24A-4936-9FC9-AF930FE3FA40/NDP461-KB3102436-x86-x64-AllOS-ENU.exe"; HttpDownLoad.

Android关于listview中显示网络图片的问题

在listview中第二次下载图片时就会出现 SkAndroidCodec::NewFromStream returned null 可能是图片大了点,它第一次还没下载完就第二次开始调用了 所以我采取的措施就是:既然每次下载图片都是在子线程中执行的,于是我在外面(循环里面)等待子线程调用完毕后再进行下一张图片的下载 以下是我 部分中的 完整代码 List<Map<String, Object>> data = new ArrayList<Map<String, Obje

ImageLoader在Listview中的使用

图片加载框架之ImageLoader 1_特点 1)多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等 2)支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置 3)支持图片的内存缓存,文件系统缓存或者SD卡缓存 4)支持图片下载过程的监听 5)根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存 6)较好的控制图片的加载过程,例如暂停图片加载,重

根据url路径获取图片并显示到ListView中

项目开发中我们需要从网络获取图片显示到控件中,很多开源框架如Picasso可以实现图片下载和缓存功能.这里介绍的是一种简易的网络图片获取方式并把它显示到ListView中. 本案例实现的效果如下: 项目结构: 根据部分开源代码,我修改并封装了一个网络图片加载的工具类GetImageByUrl,通过调用其中的setImage方法,传入待显示图片的ImageView控件和该图片的url路径这两个参数即可实现获取网络图片的功能. GetImageByUrl.java package com.leo.i

使用Volley框架的ImageLoader加载网络图片

Volley框架在请求网络图片方面也做了很多工作,提供了好几种方法.本文介绍使用ImageLoader来进行网络图片的加载. ImageLoader的内部使用ImageRequest来实现,它的构造器可以传入一个ImageCache缓存形参,实现了图片缓存的功能,同时还可以过滤重复链接,避免重复发送请求. 下面是ImageLoader加载图片的实现方法: public void displayImg(View view){ ImageView imageView = (ImageView)thi

LISTVIEW嵌套GRIDVIEW的一些处理(点击GRIDVIEW的条目,能够显示他在LISTVIEW中的位置)(对这篇文章的优化处理,不每次都new onItemClickListener)

前几天写了点击GRIDVIEW的条目,能够显示他在LISTVIEW中的位置,当时的处理是在ListView的适配器里的GetView方法里每次都new GridView的onItemClickListener,这样显然是不合理的, /**GridVIew的条目点击监听*/ private GvOnItemClickListener mGvOnItemClickListener;//成员 这是Fragment的入口: @Override public View onCreateView(Layou

Android之ListView异步加载图片且仅显示可见子项中的图片

折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整实例都没看到,只有自己一点点研究了,总体感觉 android 下面要显示个图片真不容易啊. 项目主要实现的功能: 异步加载图片图片内存缓存.异步磁盘文件缓存解决使用 viewHolder 后出现的图片错位问题优化列表滚动性能,仅显示可见子项中的图片无需固定图片显示高度,对高度进行缓存使列表滚动时不会