android listview 异步加载问题

============问题描述============

学做android,自己想模仿QQ空间做一个小demo

listview异步加载图片的时候遇到了一个问题

异步加载用到了SoftReference 和文件缓存的方法

每次加载图片的时候,也在内存或缓存中找到了图片

第一次加载出来后,listview滑动了,同样也进到了setImageBitmap这一步

可是就是图片显示不出来变成空白

下面帖几张图和代码

滑动前

滑动后

Image_url = new StringBuffer(AppConstant.DOWNLOAD_IMAGE_URL)

					.append(msg.getOPImageList().get(0).getImageUrl())

					.toString();

			ImageView imageView = holder.msgImage;

			imageView.setTag(Image_url);

			Bitmap bitmap = Loader.loadBitmap(imageView, Image_url,

					new ImageCallBack() {

						@Override

						public void imageLoad(ImageView imageView, Bitmap bitmap) {

							if (imageView.getTag() != null

									&& imageView.getTag().equals(Image_url)) {

								imageView.setImageBitmap(bitmap);

							}

						}

					});

			Log.e("当前的postion", "" + position);

			if (bitmap == null) {

				imageView.setImageDrawable(context.getResources().getDrawable(

						R.drawable.ic_launcher));

			} else {

				imageView.setImageBitmap(bitmap);

			}

loader

public class Loader {

	/**

	 * 内存图片软引用缓冲

	 */

	private static HashMap<String, SoftReference<Bitmap>> imageCache = null;

	public Loader() {

		imageCache = new HashMap<String, SoftReference<Bitmap>>();

	}

	public static String getFileName(String url) {

		return url.substring(url.lastIndexOf(File.separator) + 1);

	}

	public static Bitmap getLocalResource(String destDir, String imageName) {

		Bitmap bmp = null;

		File imgeDir = new File(destDir);

		File cache = null;

		if (!imgeDir.exists()) { // 判断本地缓存目录是否存在

			imgeDir.mkdirs();

		} else {

			cache = new File(destDir + File.separator + imageName); // 判断该图片资源是否存在

			if (cache.exists()) { // 如果存在就根据图片的存储路径得到Bitmap对象 bm

				bmp = BitmapFactory.decodeFile(cache.getAbsolutePath());

			}

		}

		return bmp;

	}

	public static Bitmap loadBitmap(final ImageView imageView, final String imageURL,

			final ImageCallBack imageCallBack) {

		// 在内存缓存中,则返回Bitmap对象

		if (imageCache.containsKey(imageURL)) {

			SoftReference<Bitmap> reference = imageCache.get(imageURL);

			Bitmap bitmap = reference.get();

			if (bitmap != null) {

				return bitmap;

			}

		} else {

			/**

			 * 加上一个对本地缓存的查找

			 */

			String bitmapName = imageURL

					.substring(imageURL.lastIndexOf("/") + 1);

			Bitmap bitmapTemp = null;

			bitmapTemp = getLocalResource(AppConstant.TEST, bitmapName);

			if (bitmapTemp != null) {

				return bitmapTemp;

			}

		}

		final Handler handler = new Handler() {

			/*

			 * (non-Javadoc)

			 * 

			 * @see android.os.Handler#handleMessage(android.os.Message)

			 */

			@Override

			public void handleMessage(Message msg) {

				// TODO Auto-generated method stub

				imageCallBack.imageLoad(imageView, (Bitmap) msg.obj);

			}

		};

		// 如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片

		new Thread() {

			/*

			 * (non-Javadoc)

			 * 

			 * @see java.lang.Thread#run()

			 */

			@Override

			public void run() {

				// TODO Auto-generated method stub

				Bitmap bitmap = null;

				try {

					URL imageUrl = new URL(imageURL);

					HttpURLConnection conn =  (HttpURLConnection) imageUrl

							.openConnection();

					conn.setConnectTimeout(30000);

					conn.setReadTimeout(30000);

					conn.setInstanceFollowRedirects(true);

					// InputStream is = conn.getInputStream();

					InputStream in = conn.getInputStream();

					BitmapFactory.Options options = new BitmapFactory.Options();

					options.inJustDecodeBounds = false;

					options.inSampleSize = 10; // width,hight设为原来的十分一

					bitmap = BitmapFactory.decodeStream(in, null, options);

				} catch (MalformedURLException e1) {

					// TODO Auto-generated catch block

					e1.printStackTrace();

				} catch (IOException e1) {

					// TODO Auto-generated catch block

					e1.printStackTrace();

				}

				imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap));

				Message msg = handler.obtainMessage(0, bitmap);

				handler.sendMessage(msg);

				File dir = new File(AppConstant.TEST);

				if (!dir.exists()) {

					dir.mkdirs();

				}

				File bitmapFile = new File(AppConstant.TEST + File.separator

						+ imageURL.substring(imageURL.lastIndexOf("/") + 1));

				if (!bitmapFile.exists()) {

					try {

						bitmapFile.createNewFile();

					} catch (IOException e) {

						// TODO Auto-generated catch block

						e.printStackTrace();

					}

				}

				FileOutputStream fos;

				try {

					fos = new FileOutputStream(bitmapFile);

					bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);

					fos.close();

				} catch (FileNotFoundException e) {

					// TODO Auto-generated catch block

					e.printStackTrace();

				} catch (IOException e) {

					// TODO Auto-generated catch block

					e.printStackTrace();

				}

			}

		}.start();

		return null;

	}

	/**

	 * 回调接口

	 * 

	 * @author onerain

	 * 

	 */

	public interface ImageCallBack {

		public void imageLoad(ImageView imageView, Bitmap bitmap);

	}

}

坐等大神支招啊

每次都进了setimagebitmap这一步 就是加载不出图片

============解决方案1============

你用imageLoader这个三方开源库试试。

============解决方案2============

看一下你imageview控件设的是src还是background。或者试试把bitmap转成drawable,再setbackground试试

============解决方案3============

看下getView方法?

============解决方案4============

贴下Adapter的代码看看呗

============解决方案5============

你试试AsyncImage这个第三方开源库

============解决方案6============

ImageView imageViewByTag = (ImageView) listview

.findViewWithTag(imageUrl);

问题应该在这一句 你这个搜索 只会找到第一个TAG 是imageUrl的控件。 可能并不是你的要更新的控件。

比如  你setTAG了  , listView 会重用item的,   在 msg.getOPImageList().size()=0 时候 还是有这个tag。

然后你find的结果就是这个contentView里面的,不是你要更新的那个ImageView。

============解决方案7============

引用

Image_url = new StringBuffer(AppConstant.DOWNLOAD_IMAGE_URL)

.append(msg.getOPImageList().get(0).getImageUrl())

.toString();

ImageView imageView = holder.msgImage;

imageView.setTag(Image_url);

Bitmap bitmap = Loader.loadBitmap(imageView, Image_url,

new ImageCallBack() {

@Override

public void imageLoad(ImageView imageView, Bitmap bitmap) {

if (imageView.getTag() != null

&& imageView.getTag().equals(Image_url)) {

imageView.setImageBitmap(bitmap);

}

}

});

Log.e("当前的postion", "" + position);

if (bitmap == null) {

imageView.setImageDrawable(context.getResources().getDrawable(

R.drawable.ic_launcher));

} else {

imageView.setImageBitmap(bitmap);

}

这个代码中  在 ImageCallBack 接口中 吧imageUrl 回传回来,跟imageView.getTag() 进行比较,应该可以解决问题。试试看。

时间: 2024-10-18 13:02:14

android listview 异步加载问题的相关文章

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

网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Ite

android listview 异步加载图片并防止错位+双缓存

网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Ite

又优化了一下 Android ListView 异步加载图片

写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看了这篇文章而受到了启发. 先说说这篇文章的优点把,开启线程异步加载图片,然后刷新UI显示图片,而且通过弱引用缓存网络加载的图片,节省了再次连接网络的开销. 这样做无疑是非常可取的方法,但是加载图片时仍然会感觉到轻微的卡屏现象,特别是listview里的item在进行快速滑动的时候. 我找了一下原因,

android listview 异步加载图片并防止错位 解决办法

网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Ite

Android ListView异步加载图片乱序问题,原因分析及解决方案

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/45586553 在Android所有系统自带的控件当中,ListView这个控件算是用法比较复杂的了,关键是用法复杂也就算了,它还经常会出现一些稀奇古怪的问题,让人非常头疼.比如说在ListView中加载图片,如果是同步加载图片倒还好,但是一旦使用异步加载图片那么问题就来了,这个问题我相信很多Android开发者都曾经遇到过,就是异步加载图片会出现错位乱序的情况.遇到这个问题时,不

android listview异步加载图片错位,重复,闪烁分析以及解决方案

我们在使用listview异步加载图片 的时候,在快速滑动或者网络不好的情况下,会出现图片错位,重复,闪烁等问题,其实这些问题总结起来就是一个问题, 比如listview上有100个item,一屏只显示10个item,我们知道getView()中converView是用来复用view对象的,因为一个item的view对象,而imageview控件就是view通过findViewById()获得的,而我们在复用view对象时,也就是说这个imageview也被复用了,比如第11个item的view

Android ListView异步加载图片错位、重复、闪烁分析以及解决方案

我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如ListView上有100个Item,一屏只显示10个Item,我们知道getView()中convertView是用来复用View对象的,因为一个Item的对应一个View对象,而ImageView控件就是View对象通过findViewById()获得的,而我们在复用View对象时,同时这个Ima

Android ListView异步加载数据

1.主Activity 1 public class MainActivity extends Activity { 2 3 private ListView listView; 4 private ArrayList<Person> persons; 5 private ListAdapter adapter; 6 private Handler handler=null; 7 //xml文件的网络地址 8 final String path="http://192.168.5.1

android开发干货:实现listview异步加载图片

针对listview异步加载图片这个问题,麦子学院android开发老师讲了一种非常实用的方法,麦子学院android开发老师说凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReference; import java.net.