码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-05-02 09:46:59      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:imageloader在listview   handler机制   

首先,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两个属性就不贴代码出来了。结果截图


技术分享技术分享


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

标签:imageloader在listview   handler机制   

原文地址:http://blog.csdn.net/liweijie_chengxuyuan/article/details/45422055

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!