天天看點

Android ListView異步加載圖檔錯位問題解析

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">       我們使用ListView的時,經常在ListView Item的布局裡會異步加載一些圖檔。然後我通常會使用</span><a target=_blank href="https://github.com/nostra13/Android-Universal-Image-Loader" target="_blank" rel="external nofollow"  target="_blank" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">universalimageloader</a><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">這個開源架構,但是會發現,當滑動ListView時候,會出現圖檔的錯位和閃動的現象。一開始不知道什麼原因,今天才弄明白,分享一下。</span>
           

首先看一下這個圖,

Android ListView異步加載圖檔錯位問題解析

想必大家一看就會明白了,一般我們在使用ListView的時候都會使用到

@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = LayoutInflater.from(context).inflate(
					R.layout.list_item, null);
					

			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		/**
		 *  添加自己的代碼
		 * 
		 */


		return convertView;
	}
           

也就是上面圖示的原理:一開始加載裝置可見Item的布局,幾new 了7個convertView執行個體,之後的從低8個開始,就複用前面的convertView。又一個關鍵是,我們在加載圖檔的時候又是異步加載的(紅色文字),

@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		final String imgUrl = list[position];
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = LayoutInflater.from(context).inflate(
					R.layout.list_item, null);
			holder.img = (NetworkImageView) convertView
					.findViewById(R.id.userimage);
			holder.loderImageView = (ImageView) convertView.findViewById(R.id.loder_imageView);
			

			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		if (imgUrl != null && !imgUrl.equals("")) {
			<strong><span style="color:#ff0000;">com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(imgUrl, holder.loderImageView);</span></strong>
		}

		return convertView;
	}
           

是以當Item8出現的時候,回複用 item 1的布局,包括為Item設定的控件的值也會複用,是以此時由于加載圖檔是異步的,是以當Item 8出現在螢幕的時候,顯示的是Item 1的内容,而此時Item 8所加載的圖檔還沒有加載完畢,是以你看到的是Item1的圖檔,當Item 8的圖檔加載完成以後,又會覆寫Item所顯示的圖檔,是以我們看到的現象是圖檔有錯位的和閃爍。此時我們就會明白為真正的原因了,接下來如何去解決它呢?

我也參考他人的做法就是為每一個ImageView設定一個不同的Tag,然後在圖檔加載的時候判讀這個Tag ,如果相同才顯示圖檔。但是我可能比較笨,沒能很好的了解,是以也不敢告訴大家,有了解的朋友可以告訴我,我會感激不盡。但是我現在告訴大家的是,像這種情況我們可以使用Volley的NetworkImageView,代碼如下:

@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		final String imgUrl = list[position];
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = LayoutInflater.from(context).inflate(
					R.layout.list_item, null);
			holder.img = (NetworkImageView) convertView
					.findViewById(R.id.userimage);
			holder.loderImageView = (ImageView) convertView.findViewById(R.id.loder_imageView);
			
			if (imgUrl != null && !imgUrl.equals("")) {
				holder.img.setDefaultImageResId(R.drawable.ic_launcher);
				holder.img.setErrorImageResId(R.drawable.ic_launcher);
				holder.img.setImageUrl(imgUrl, imageLoader);
//				com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(imgUrl, holder.loderImageView);
			}
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		return convertView;
	}
           

/res/layout/list_view

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    
    <LinearLayout 
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:orientation="vertical">
        <TextView 
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="這是通過volley加載的圖檔"/>

    <<span style="color:#cc33cc;"><strong>com.android.volley.toolbox.NetworkImageView</strong></span>
        android:id="@+id/userimage"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    </LinearLayout>
    
    <LinearLayout 
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:orientation="vertical">
         <TextView 
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="這是通過imageLoader加載的圖檔"/>
    
    <ImageView 
        android:id="@+id/loder_imageView"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    </LinearLayout>
    
</LinearLayout>
           

然後我做了一個比較,使用 Volley的NetworkImageView不會出現錯位,而 UniversalImage Loader會出現。而且通過 NetworkImageView加載圖檔使用非常的簡單,大家可以嘗試一下。

提供源碼下載下傳,可以試一試。這是在CSDN第一篇部落格,希望的得到好評,不喜勿噴哦!

Android ListView異步加載圖檔錯位問題解析