2015-07-04 132 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

相关问题