我正在进行一个包含listview的活动。列表视图由从服务器提取的大型XML填充。 我的方案通常是拥有一个SAX解析器,解析XML并返回一个带有解析数据的Vector(或类似结构)。 问题是xml太大而Vector有太多元素导致内存不足错误。 此外,xml还有正在下载的图像的链接,这使情况更糟。
在这种情况下我应该如何管理内存?我想是否只有当用户滚动到列表视图中的给定行时才能加载图像。
答案 0 :(得分:2)
内存不足异常的问题是加载图像。在Adapter
中填充自己ListView
应该没有问题。
在业务应用程序中,我正在加载ListView
,其中包含9000条记录,每行有2 TextView
个。所以我猜数据的大小应该不是问题。
使用AsyncTask
从服务器获取数据。使用doInBackground()
方法解析并填充适配器,然后在onPostExecute()
中将适配器设置为ListView
。首先尝试不要包含任何图像,以确保数据大小不是问题。
如果ListView
正确加载,请尝试找到填充图像的方法。执行此操作有多种方法。如果图像一遍又一遍,你应该尝试“在内存中缓存”实现,否则从后台线程“lazyloading”应该可以正常工作。
编辑:
这是一个关于如何从后台线程延迟加载图像的非常好的帖子/教程。当你在GridView
中查看所有应用程序时,它几乎与Android市场使用的技术相同,一开始有一些灰色图标,然后突然显示应用程序的图像。这是从后台线程完成的,当用户看到确切的行然后后台线程从互联网上获取它时,填充列表并将其缓存在内存中以便立即再次可用。 Lazy load of images in ListView
答案 1 :(得分:0)
使用service
将XML从服务器拉入database
。您的activity
懒得加载来自database
的数据,就像您在Google Play中看到的那样。见CWAC EndlessAdapter。也可以看看
Universal Image Loader for Android以listview
填充图片。
答案 2 :(得分:0)
OutOfMemoryException很可能是由图像引起的。
假设您想要显示带图片的酒店列表。您将获得XML格式的酒店信息并将其保存在List(或类似结构)中。您的酒店类可能会有URL pictureURL
之类的成员和WeakReference<Drawable> picture
之类的成员,在需要之前会为空。
您可以使列表适配器启动AsyncTask
以在getView()方法中下载图像(如果图片指向null)并将其设置为列表中的ImageView和Hotel.picture
因为Hotel.picture是一个弱引用,当ImageViews
被回收时,图像离开屏幕时将释放内存
您的getView方法可能包含以下内容:
private class MyCustomAdapter extends BaseAdapter {
...
List<Hotel> hotelList;
...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
Hotel hotel = hotelList.get(position);
ImageView ivHotelPic = //your image view from the list (child of 'view')
...
if (hotel.picture == null || hotel.picture.get() == null){
new DownloadImageTask(hotel,ivHotelPic).execute(hotel.pictureURL)
}
else{
ivHotelPic.setImageDrawable( hotel.picture.get() );
}
return view;
}
}
private class DownloadImageTask extends AsyncTask<URL, Integer, Drawable> {
Hotel hotel;
ImageView imageView;
DownloadImageTask(Hotel hotel,ImageView imageView){
this.hotel = hotel;
this.imageView = imageView;
}
protected Drawable doInBackground(URL... urls) {
assert urls.length == 1;
Drawable image = //download image from urls[0] (or hotel.pictureURL);
return image;
}
protected void onPostExecute(Drawable result) {
imageView.setImageDrawable(result);
hotel.picture = new WeakReference<Drawable>(result);
}
}
如果您希望在活动结束前保留图片,也可以使用常规参考,但如果下载了太多图片,这可能会导致OutOfMemory。