2015-07-04 139 views
0

我試圖在sdcard文件夾中找到所有視頻的縮略圖,並使用Picasso圖像加載程序在列表視圖中填充所有生成的位圖。一切正常,但它非常緩慢,我無法滾動列表瀏覽它的滯後非常緩慢。我在那個列表視圖中有大約150個視圖。任何幫助? 。謝謝提前。在Picasso中加載位圖圖像圖像加載器會減慢在列表視圖中的滾動

public class VideoFilesAdapter extends ArrayAdapter<String> { 
    private List<String> mpath; 
    private Context mContext; 
    public static ArrayList<String> mSelectedPaths = null; 

    public VideoFilesAdapter(Context context, List<String> path) { 
     super(context, R.layout.fileadapter_list, path); 
     this.mContext = context; 
     this.mpath = path; 
    } 

    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     if (convertView == null) { 
      LayoutInflater mInflater = (LayoutInflater) mContext 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = mInflater.inflate(R.layout.fileadapter_list, null); 
     } 
     TextView txtTitle = (TextView) convertView.findViewById(R.id.txt); 
     ImageView imageView = (ImageView) convertView.findViewById(R.id.img); 

     File file = new File(mpath.get(position)); 

     if (file.exists()) { 

      txtTitle.setText(file.getName()); 

      Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(
        file.getAbsolutePath(), 
        MediaStore.Video.Thumbnails.MICRO_KIND); 

      Picasso.with(mContext).load(getImageUri(mContext, bitmap)) 
        .centerInside().resize(100, 100) 
        .placeholder(R.drawable.holder).error(R.drawable.error) 
        .into(imageView); 

     } 

     return convertView; 
    } 

    public Uri getImageUri(Context inContext, Bitmap inImage) { 
     ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
     inImage.compress(Bitmap.CompressFormat.JPEG, 20, bytes); 
     String path = Images.Media.insertImage(inContext.getContentResolver(), 
       inImage, "Title", null); 
     return Uri.parse(path); 
    } 

} 
+0

你的代碼的問題是,你的膨化的TextView和ImageView的細胞每次視圖被回收,基本上就會放慢您的滾動體驗。 – neferpitou

+0

那麼這個解決方案是什麼? @Dragon –

+0

林編碼現在,我可能會在明天寄給你:)我會盡我所能解釋每一個部分。 – neferpitou

回答

0

更新 它看起來並不像你存儲/以任何方式緩存的位圖,所以它是一遍又一遍這樣做。嘗試在這裏找到了解決辦法:Video thumbnail arrayadopter is slow on scroll


我不認爲畢加索是放慢您的ListView的滾動。你的列表項目有多複雜?如果他們嵌套了很多觀點,那可能就是這樣,我在ListView中有超過700件物品,沒有任何性能問題。

+0

我知道減速是因爲'ThumbnailUtils.createVideoThumbnail'函數生成文件夾中所有視頻文件的縮略圖。有沒有解決它的方法。 –

+0

已更新回答:) – orrett3

0

當我回顧我見過的代碼TextViewImageView每次調用getView時都會被誇大。通貨膨脹是一項非常昂貴的任務,所以我們希望儘可能避免使用它。

之前別的確保你會在你的搖籃聲明它

compile 'com.android.support:support-v4:21.0.0' 

添加這個輔助類的VideoFilesAdapter.java

class Helper { 
     public TextView textView; 
     public ImageView image; 
    } 

然後,我們將使用LRUcache在存儲圖像,這樣我們就可以使用這個圖像一遍又一遍,沒有做任何事情。

在項目中添加MyLRU.java

import android.content.Context; 
import android.graphics.Bitmap; 
import android.support.v4.util.LruCache; 

public class MyLRU { 

    private LruCache<String, Bitmap> cache = null; 
    private static MyLRU myLru = null; 

    private MyLRU() { 
     int availableMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 
     cache = new LruCache<String, Bitmap>(availableMemory/8) { 
      @Override 
      protected int sizeOf(String key, Bitmap value) { 
       // this is the only way to get the Bitmap size below API 12 
       return (value.getRowBytes() * value.getHeight())/1024; 
      } 
     }; 
    } 

    public static MyLRU getInstance() { 
     if (myLru == null) { 
      myLru = new MyLRU(); 
     } 
     return myLru; 
    } 

    public void addImage(String key, Bitmap image) { 
     myLru.addImage(key, image); 
    } 

    public Bitmap getImage(String key) { 
     return myLru.getImage(key); 
    } 

} 

VideoFilesAdapter.java

public static Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth) { 
     int sourceWidth = source.getWidth(); 
     int sourceHeight = source.getHeight(); 

     // Compute the scaling factors to fit the new height and width, respectively. 
     // To cover the final image, the final scaling will be the bigger 
     // of these two. 
     float xScale = (float) newWidth/sourceWidth; 
     float yScale = (float) newHeight/sourceHeight; 
     float scale = Math.max(xScale, yScale); 

     // Now get the size of the source bitmap when scaled 
     float scaledWidth = scale * sourceWidth; 
     float scaledHeight = scale * sourceHeight; 

     // Let's find out the upper left coordinates if the scaled bitmap 
     // should be centered in the new size give by the parameters 
     float left = (newWidth - scaledWidth)/2; 
     float top = (newHeight - scaledHeight)/2; 

     // The target rectangle for the new, scaled version of the source bitmap will now 
     // be 
     RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight); 

     // Finally, we create a new bitmap of the specified size and draw our new, 
     // scaled bitmap onto it. 
     Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig()); 
     Canvas canvas = new Canvas(dest); 
     canvas.drawBitmap(source, null, targetRect, null); 

     return dest; 
    } 

添加一個實用的方法在這裏是你的VideoFilesAdapter.java

public class VideoFilesAdapter extends ArrayAdapter<String> { 
    private List<String> mpath; 
    private Context mContext; 
    public static ArrayList<String> mSelectedPaths = null; 
    private MyLRU lruCache; 

    public VideoFilesAdapter(Context context, List<String> path) { 
     super(context, R.layout.fileadapter_list, path); 
     this.mContext = context; 
     this.mpath = path; 
     // My LRU 
     lruCache = MyLRU.getInstance(); 
    } 

    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     View v; 
     if (convertView == null) { 
      LayoutInflater mInflater = (LayoutInflater) mContext 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = mInflater.inflate(R.layout.fileadapter_list, null); 
      Helper h = new Helper(); 
      h.textView = (TextView) convertView.findViewById(R.id.txt); 
      h.textView = (ImageView) convertView.findViewById(R.id.img); 
      v.setTag(h); 
     } else { 
      v = convertView; 
     } 

     Helper myHelper = (Helper) v.getTag(); 

     File file = new File(mpath.get(position)); 
     String fullPath = file.getAbsolutePath(); 

     if (file.exists()) { 
      myHelper.textView.setText(file.getName()); 

      Bitmap cacheImage = lruCache.getImage(fullPath); 
      if (cacheImage == null) { 
       Bitmap bm = scaleCenterCrop(ThumbnailUtils.createVideoThumbnail(fullPath, MediaStore.Video.Thumbnails.MICRO_KIND),100,100); 
       lruCache.addImage(fullPath, bm); 
       cacheImage = bm; 
      } 
      myHelper.image.setImageBitmap(cacheImage); 

     } 

     return v; 
    } 

    class Helper { 
     public TextView textView; 
     public ImageView image; 
    } 

    public static Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth) { 
     int sourceWidth = source.getWidth(); 
     int sourceHeight = source.getHeight(); 

     // Compute the scaling factors to fit the new height and width, respectively. 
     // To cover the final image, the final scaling will be the bigger 
     // of these two. 
     float xScale = (float) newWidth/sourceWidth; 
     float yScale = (float) newHeight/sourceHeight; 
     float scale = Math.max(xScale, yScale); 

     // Now get the size of the source bitmap when scaled 
     float scaledWidth = scale * sourceWidth; 
     float scaledHeight = scale * sourceHeight; 

     // Let's find out the upper left coordinates if the scaled bitmap 
     // should be centered in the new size give by the parameters 
     float left = (newWidth - scaledWidth)/2; 
     float top = (newHeight - scaledHeight)/2; 

     // The target rectangle for the new, scaled version of the source bitmap will now 
     // be 
     RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight); 

     // Finally, we create a new bitmap of the specified size and draw our new, 
     // scaled bitmap onto it. 
     Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig()); 
     Canvas canvas = new Canvas(dest); 
     canvas.drawBitmap(source, null, targetRect, null); 

     return dest; 
    } 

} 

完全修改正如你可以看到我暫時取消getImageUri方法和畢加索,因爲它已經沒有意義了,因爲我們已經有一個緩存,它是LRU緩存。

我希望這將提高應用性能:)

+0

07-05 23:14:17.282:E/AndroidRuntime(4681):java.lang.StackOverflowError:stack size 8MB 07-05 23:14:17.282:E/AndroidRuntime(4681):\t at com.example.myapp.helper.MyLRU.getImage(MyLRU。java:34) –

+0

發生這種情況時,我打開一些文件夾,其中有一些150視頻文件.. –

+0

我認爲問題是你的設備是內存不足,請嘗試更改** availableMemory/8 **到** availableMemory/4 * *讓我知道會發生什麼。 – neferpitou

相關問題