2012-08-23 133 views
1

我創建了一個自定義ListView,其中我將圖像作爲列表項顯示。作爲列表項目顯示的圖像存儲在設備的我的InternalStorage中,我注意到當項目數超過7時,列表視圖滾動變慢,滾動時ListView中的項目變得很慢。我的代碼有什麼問題,或者錯過了我的代碼。請幫我解決這個問題。ListView從內部存儲器加載圖像時滾動緩慢

代碼顯示列表視圖項

public class ListViewAdapter extends BaseAdapter 
    { 
     private Activity activity; 
     private ArrayList<String> fileNameArray; 
     private LayoutInflater inflater=null; 
     public ImageLoader imageLoader; 

     public ListViewAdapter(Activity a, ArrayList<String> d) 
     { 
      activity = a; 
      fileNameArray = d; 
      inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      imageLoader = new ImageLoader(activity.getApplicationContext()); 
     } 

     public int getCount() 
     { 
      return fileNameArray.size(); 
     } 

     public Object getItem(int position) 
     { 
      return position; 
     } 

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

     public class ViewHolder 
     { 
      ImageView image; 
     }    

     public View getView(final int position, View convertView, ViewGroup parent) 
     { 
      ViewHolder holder; 

      if(convertView == null) 
      { 
       holder = new ViewHolder(); 
       convertView = inflater.inflate(R.layout.page_list_item, null); 

       holder.image = (ImageView)convertView.findViewById(R.id.image); 

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



      // Load image from internalstoarage and display in image view 

      imageLoader.DisplayImage(m_DirectoryPath.getPath() + "/" + fileNameArray.get(position), holder.image, true); 

      return convertView; 
     } 
} 

代碼圖像加載器類

public class ImageLoader 
{ 
    MemoryCache memoryCache = new MemoryCache(); 
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
    ExecutorService executorService; 
    Context m_context; 
    public ImageLoader(Context context) 
    { 
     m_context = context; 
     executorService = Executors.newFixedThreadPool(5); 
    } 

    public void DisplayImage(String url, ImageView imageView, boolean useCachedImage) 
    { 
     imageViews.put(imageView, url); 
     Bitmap bitmap = memoryCache.get(url); 

     if(bitmap!=null && useCachedImage) 
     { 
      imageView.setImageBitmap(bitmap); 
     } 
     else 
     { 
      queuePhoto(url, imageView); 
     } 
    } 

    private void queuePhoto(String url, ImageView imageView) 
    { 
     PhotoToLoad p = new PhotoToLoad(url, imageView); 
     executorService.submit(new PhotosLoader(p)); 
    } 

    private Bitmap getBitmap(String url) 
    { 
     File filePath = new File(url); 

     // from internal storage cache 
     Bitmap b = decodeFile(filePath); 
     if (b != null) 
     { 
      return b; 
     } 
     return null; 
    } 

    // decodes image and scales it to reduce memory consumption 
    private Bitmap decodeFile(File filePath) 
    { 
     try 
     { 
      // decode image size 
      int Required_Height = 0; 

      BitmapFactory.Options option = new BitmapFactory.Options();    
      Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(filePath), null, option); 

      WindowManager wm = (WindowManager) m_context.getSystemService(Context.WINDOW_SERVICE); 
      Display display = wm.getDefaultDisplay(); 

      if(display.getWidth() == 480) 
      { 
       Required_Height = 150; 
      } 
      else if(display.getWidth() == 800) 
      { 
       Required_Height = 200; 
      } 

      bitmap = Bitmap.createBitmap(bitmap, 0, 0, option.outWidth, Required_Height); 

      return bitmap; 
     } 
     catch (FileNotFoundException e){    
     } 
     return null; 
    } 

    // Task for the queue 
    private class PhotoToLoad 
    { 
     public String url; 
     public ImageView imageView; 
     public PhotoToLoad(String u, ImageView i) 
     { 
      url = u; 
      imageView=i; 
     } 
    } 

    class PhotosLoader implements Runnable 
    { 
     PhotoToLoad photoToLoad; 
     PhotosLoader(PhotoToLoad photoToLoad) 
     { 
      this.photoToLoad = photoToLoad; 
     } 

     @Override 
     public void run() 
     { 
      if(imageViewReused(photoToLoad)) 
       return; 

      Bitmap bmp = getBitmap(photoToLoad.url); 
      memoryCache.put(photoToLoad.url, bmp); 

      if(imageViewReused(photoToLoad)) 
       return; 

      BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad); 
      Activity a = (Activity)photoToLoad.imageView.getContext(); 
      a.runOnUiThread(bd); 
     } 
    } 

    boolean imageViewReused(PhotoToLoad photoToLoad) 
    { 
     String tag = imageViews.get(photoToLoad.imageView); 

     if(tag == null || !tag.equals(photoToLoad.url))   
      return true; 

     return false; 
    } 

    // Used to display bitmap in the UI thread 
    class BitmapDisplayer implements Runnable 
    { 
     Bitmap bitmap; 
     PhotoToLoad photoToLoad; 
     public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;} 
     public void run() 
     { 
      if(imageViewReused(photoToLoad)) 
       return; 

      if(bitmap != null) 
       photoToLoad.imageView.setImageBitmap(bitmap); 
     } 
    } 

    public void clearCache() 
    { 
     memoryCache.clear(); 
    } 

} 

回答

1

你必須setPriority爲PhotosLoader線程對象。我正在做這樣的構造函數。

// Make the background thread low priority. This way it will not affect the UI performance 
mImageRequstController.setPriority(Thread.NORM_PRIORITY - 1); 

通過優先權少於正常,它不會影響用戶界面,並將繼續其在後臺工作。

+0

如何做到這一點..可以請你解釋我,我怎麼能在我的代碼 – Rahul

+0

請分享你的代碼爲Executors.newFixedThreadPool(5); – Arslan

+0

我沒有任何代碼,這是一個由ExecutorService類提供的默認方法 – Rahul

0

發生什麼事情是出於速度的原因,直到需要時纔會加載視圖外的列表項。當用戶將列表項目滾動到視圖中時,它將被加載。但是,從SD卡加載圖像是一項耗時的操作,足以讓用戶看到滯後。

您的代碼會在UI線程中加載圖像,阻止它更新並平滑滾動列表。相反,您應該將圖像加載到另一個線程上,而UI線程上的列表項應該只顯示進度微調器或其他加載指示器,直到加載圖像。而且,像列表一樣,線程只能在列表項目被查看時啓動,而不是一次全部啓動。

+0

我看了很多例子,在單獨的線程中加載用戶界面,但無法得到我如何在我的代碼中實現它..你可以幫我要知道我該如何在我的代碼中做到這一點 – Rahul

+0

@RahulBorah:不,我不會告訴你代碼。如果我沒有學習,我會鼓勵你複製粘貼。我寧願你理解它。但是,這樣做相當微不足道。將圖像設置爲加載進度圖像。啓動一個簡單的將圖像加載到Bitmap或其他內容的線程。線程完成後,它會調用一個Handler將圖像放入視圖中。就這樣。 – AlbeyAmakiir