从大型XML填充ListView

时间:2012-07-23 07:40:48

标签: android xml listview memory-management

我正在进行一个包含listview的活动。列表视图由从服务器提取的大型XML填充。 我的方案通常是拥有一个SAX解析器,解析XML并返回一个带有解析数据的Vector(或类似结构)。 问题是xml太大而Vector有太多元素导致内存不足错误。 此外,xml还有正在下载的图像的链接,这使情况更糟。

在这种情况下我应该如何管理内存?我想是否只有当用户滚动到列表视图中的给定行时才能加载图像。

3 个答案:

答案 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 Androidlistview填充图片。

答案 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。