我正在尝试生成sdcard文件夹中找到的所有视频的缩略图,并使用Picasso Image loader在listview中填充所有生成的位图。一切正常,但它非常慢,我无法滚动浏览它的滞后非常缓慢。我在该列表视图中有大约150个视图。任何帮助?谢谢,谢谢。
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 :(得分:0)
<强>更新强> 它看起来不像是以任何方式存储/缓存这些位图,所以它一遍又一遍地进行。试试这里找到的解决方案:Video thumbnail arrayadopter is slow on scroll
我不认为毕加索正在减慢你ListView
的滚动速度。您的列表项有多复杂?如果它们嵌套了许多视图,那可能是它,我在ListView
中有超过700个项目没有性能问题。
答案 1 :(得分:0)
在我查看代码时,我看到每次调用TextView
时ImageView
和getView
都会被充气。通货膨胀是一项非常昂贵的任务,因此我们希望尽可能避免使用它。
在任何其他事项之前确保您将在Gradle中声明它
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
方法和Picasso,因为它已经没有意义了,因为我们已经有了LRU-cache的缓存。
我希望这会提高您的应用效果:)