caw*_*caw 5 memory android android-listview android-imageview
对于各种Android应用程序,我需要大ListViews,即具有100-300个条目的此类视图.
启动应用程序时,必须批量加载所有条目,因为某些排序和处理是必需的,并且应用程序无法知道首先显示哪些项目,否则.
到目前为止,我一直在批量加载所有项目的图像,然后将其ArrayList<CustomType>与每个条目的其余数据一起保存.
但是,当然,这不是一个好的做法,因为你很可能有一个OutOfMemoryException当时:对所有图像的引用ArrayList阻止垃圾收集器工作.
因此,最好的解决方案显然只是批量加载文本数据,然后根据需要加载图像,对吧?Google Play应用程序执行此操作,例如:您可以看到图像在滚动到它们时加载,即它们可能已加载到适配器的getView()方法中.但是对于谷歌播放,这是一个不同的问题,因为图像必须从互联网加载,这对我来说并非如此.我的问题不是加载图像需要太长时间,但存储它们需要太多内存.
那么我该如何处理图像呢?在getView()真正需要时装入?会使滚动迟缓.那么打电话给AsyncTask那么?还是只是正常Thread?参数化吗?
我可以将已加载的图像保存到a中HashMap<String,Bitmap>,这样就不需要再次加载它们了getView().但如果这样做了,你又会遇到内存问题:HashMap商店会引用所有图片,所以最后你可以OutOfMemoryException再次使用.
我知道这里已经有很多问题讨论图像的"延迟加载".但它们主要涵盖了加载缓慢的问题,而不是太多的内存消耗.
编辑:我现在决定在getView()中启动AsyncTasks,它将图像加载到后台的ListView中.但这会导致我的应用程序遇到RejectedExecutionException.我现在应该怎么做?
我采用了使用AsyncTask加载图像的方法,并将任务附加到适配器的getView函数中的视图,以跟踪在哪个视图中加载哪个任务.我在我的应用程序中使用它,没有滚动滞后,所有图像都加载到正确的位置,没有异常被抛出.此外,因为如果任务被取消,该任务不起作用,您可以在列表上执行任务并且它应该落后.
任务:
public class DecodeTask extends AsyncTask<String, Void, Bitmap> {
private static int MaxTextureSize = 2048; /* True for most devices. */
public ImageView v;
public DecodeTask(ImageView iv) {
v = iv;
}
protected Bitmap doInBackground(String... params) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPurgeable = true;
opt.inPreferQualityOverSpeed = false;
opt.inSampleSize = 0;
Bitmap bitmap = null;
if(isCancelled()) {
return bitmap;
}
opt.inJustDecodeBounds = true;
do {
opt.inSampleSize++;
BitmapFactory.decodeFile(params[0], opt);
} while(opt.outHeight > MaxTextureSize || opt.outWidth > MaxTextureSize)
opt.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(params[0], opt);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
if(v != null) {
v.setImageBitmap(result);
}
}
}
Run Code Online (Sandbox Code Playgroud)
适配器存储一个ArrayList,其中包含所有需要加载的图像的文件路径.getView函数如下所示:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView iv = null;
if(convertView == null) {
convertView = getLayoutInflater().inflate(R.id.your_view, null); /* Inflate your view here */
iv = convertView.findViewById(R.id.your_image_view);
} else {
iv = convertView.findViewById(R.id.your_image_view);
DecodeTask task = (DecodeTask)iv.getTag(R.id.your_image_view);
if(task != null) {
task.cancel(true);
}
}
iv.setImageBitmap(null);
DecodeTask task = new DecodeTask(iv);
task.execute(getItem(position) /* File path to image */);
iv.setTag(R.id.your_image_view, task);
return convertView;
}
Run Code Online (Sandbox Code Playgroud)
注意:这里只是一个警告,这可能仍然会给版本1.5 - 2.3的内存问题,因为它们使用AsyncTask的线程池.3.0+默认情况下返回串行模型执行AsyncTasks,使其一次运行一个任务,因此在任何给定时间使用更少的内存.只要你的图像不是太大,你应该没问题.
| 归档时间: |
|
| 查看次数: |
8350 次 |
| 最近记录: |