2013-10-08 48 views
0

我在每一行都有一個帶有ImageView的ListView。有什麼方法可以提高從資產加載圖像的性能?

我有一個customAdapter爲getView函數中的每一行加載圖像。

public View getView(int position, View convertView, ViewGroup parent) { 

    View row = convertView; 
    if (row == null) { 
     LayoutInflater inflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     row = inflater.inflate(R.layout.list_row, parent, false); 
     ViewHolder viewHolder = new ViewHolder(); 
     viewHolder.listImage = (ImageView) row 
       .findViewById(R.id.list_image); 
     viewHolder.title = (TextView) row.findViewById(R.id.title); 
     viewHolder.description = (TextView) row 
       .findViewById(R.id.description); 
     row.setTag(viewHolder); 

    } 


    ItemDescription des = getItemDescriptionFromFile(items.get(position) 
      + "/description.txt"); 
    ViewHolder holder = (ViewHolder) row.getTag(); 
    holder.title.setText(des.title); 
    holder.description.setText(des.description+(position)%5); 

    holder.listImage.setImageBitmap(getBitmapFromAsset(items.get(position)); 
    return row; 

} 

private Bitmap getBitmapFromAsset(String strName) { 

    InputStream istr = null; 
    try { 
     istr = assetManager.open(strName); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    Bitmap bitmap = BitmapFactory.decodeStream(istr); 
    return bitmap; 
} 

但是我注意到列表的滾動不夠光滑。

我GOOGLE了我的問題,而這個鏈接似乎是解決方案: http://developer.android.com/training/improving-layouts/smooth-scrolling.html

但也存在一些問題,與此代碼:

new AsyncTask<ViewHolder, Void, Bitmap>() { 
private ViewHolder v; 

@Override 
protected Bitmap doInBackground(ViewHolder... params) { 
    v = params[0]; 
    return mFakeImageLoader.getImage(); 
} 

@Override 
protected void onPostExecute(Bitmap result) { 
    super.onPostExecute(result); 
    if (v.position == position) { 
     // If this item hasn't been recycled already, hide the 
     // progress and set and show the image 
     v.progress.setVisibility(View.GONE); 
     v.icon.setVisibility(View.VISIBLE); 
     v.icon.setImageBitmap(result); 
    } 
} 
}.execute(holder); 

我不能訪問位置內部類的AsyncTask因爲裏面位置不是最終的。

有什麼方法可以訪問位置?

什麼是使我的清單順利滾動的最佳方式是什麼?

在此先感謝。

+0

你可以看看[這](http://www.youtube.com/watch?v=KHTi28zT7rI) –

回答

0

我建議你在初始化適配器並從那裏訪問它之前,將所有資產中的圖像加載到內存中,而不是在每個getView()調用上執行磁盤I/O。這應該會導致重大改進。

+0

你的意思是我加載的OnCreate方法中的所有位圖,並將它們保存在位圖的陣列? –

+0

這將是一種方法來做到這一點。我建議在後臺線程中完成它,並在完成後初始化適配器。 –

+0

太好了,謝謝。 –

0

您可以使用具有靜態對象的類充當緩存。通過這種方式,類對象將資源緩存到第一次加載到內存中,而在下次調用中,使用緩存的訪問時間將減少。實施以下課程只需撥打Bitmaps.getBitmapFromAsset(context,strName)而不是您自己的getBitmapFromAsset(strName)。應該注意,以這種方式用於資產的內存在您離開應用程序之前不會被釋放,因爲您正在使用static HastTable對象。

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Hashtable; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 


public class Bitmaps { 

    private static final Hashtable<String, Bitmap> cache = new Hashtable<String, Bitmap>(); 

    public static Bitmap getBitmapFromAsset(Context c, String strName) { 
     synchronized (cache) { 
      if (!cache.containsKey(strName)) { 
       InputStream istr = null; 
       try { 
        istr = c.getAssets().open(strName); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
       Bitmap bitmap = BitmapFactory.decodeStream(istr); 

       cache.put(strName, bitmap); 
      } 
      return cache.get(strName); 
     } 
    } 

} 
+0

我認爲這樣列表不會第一次順利滾動。 我對不對? –

+0

每次滾動列表視圖時,都會調用每個可見行的getView。所以只需滾動一次,所有項目都會被加載。您可以在AsynchTask中加載圖像,以避免延遲,並在doInBackground中的finishig getBitmapFromAsset後顯示圖像。如果加載圖像需要太多時間,則使用提供的方法將圖像加載到系統內存中將是合理的。 – VSB

+0

如果圖像尚未加載,您可以在列表視圖中顯示一些虛擬圖像,以便滾動列表平滑器。這樣圖像將被加載,如果需要的話,用戶滾動到該行。 – VSB

相關問題