【问题标题】:Populate ListView from large XML从大型 XML 填充 ListView
【发布时间】:2012-07-23 07:40:47
【问题描述】:

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

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

【问题讨论】:

  • 我认为首先解析 XMl 并将解析的数据存储在数组或数组列表中..然后在列表视图中绑定数据..并用于图像使用延迟加载..
  • 我实现了一个 CursorAdapter,它在 bindView 期间从文件中加载图像缩略图(文件名缓存在数据库中)。
  • 使用 BaseAdapter 您可以将图像设置为延迟加载。 (关于大的xml,有多大?你的意思是你有一个包含太多对象的列表而导致内存不足??)
  • @Nuno Gonçalves 首先我认为对象太多,但后来我意识到我加载的图像太多了。我应该如何延迟加载图像?我的意思是,我可以存储图像 url,但如何知道何时加载当前应该在屏幕上的图像?
  • 我没有阅读所有答案,但我几乎可以肯定那里已经有一个有效的答案。无论如何,在 getView() 方法上,只需创建一个新线程即可从您拥有的链接将图像加载到网络上。 :) 那里有例子,如果答案没有起到作用。

标签: android xml listview memory-management


【解决方案1】:

内存不足异常的问题是图像的加载。 Adapter 在将自己填充到 ListView 时应该没有问题。

在一个业务应用程序中,我正在加载一个带有 9000 条记录的 ListView,每行有 2 个 TextViews。所以我猜数据的大小应该不是问题。

使用AsyncTask 从服务器获取数据。在doInBackground() 方法中解析和填充适配器,然后在onPostExecute() 中设置ListView 中的适配器。首先尽量不要包含任何图像,以确保数据大小不是问题。

如果ListView 正确加载,请尝试找到填充图像的方法。执行此操作有多种方法。如果图像一遍又一遍地相同,您应该尝试“缓存在内存中”实现,否则后台线程中的“延迟加载”可能会很好地完成这项工作。

编辑:

这是一篇关于如何从后台线程延迟加载图像的非常好的帖子/教程。当您查看GridView 中的所有应用程序时,它“几乎”与 android 市场使用的技术相同,起初有一些灰色图标,然后突然出现应用程序的图像。这是从后台线程完成的,当用户可以看到确切的行时,后台线程从互联网上获取它,填充列表并将其缓存在内存中,以便立即再次可用。 Lazy load of images in ListView

【讨论】:

  • 你是绝对正确的。什么是延迟加载技巧?如何知道何时从其 url 加载给定图像?我想在列表视图中的行可见时加载它,即当用户滚动到它时。
  • 再次感谢我刚刚尝试了一些东西 - 我创建了一个自定义适配器并在我有一个 ImageView 的地方实现了 getView。每当调用 getView 时我就启动了一个 AsyncTask 并且它运行良好并且滚动很流畅,但是问题是当我再次向上滚动时图像再次加载。如果列表视图以某种方式缓存它们会更好。这可能吗?我认为使用我的数据结构来保留加载的位图不是一个好主意,因为我会再次遇到内存问题。
  • 查看以上链接。当它获取图像时,它在某处有一些代码将图像缓存在map 中,当需要再次重新获取它时,程序首先检查map,如果不存在则尝试制作异步调用。但是,这是关键部分,您要填充多少不同的图像?
  • 这是我必须填充大约 400-500 张图像的问题,将它们全部缓存会再次导致内存问题。也许一个好主意是保留 10-15 个图像的上限并将它们存储在类似队列的结构(可能是简单数组)中,每当达到限制时丢弃最旧的并添加新的,这样我可以保持用户最近看到的 10 个。
  • 是的,这会导致内存不足异常。您的优化解决方案非常好,应该足够了。尽管有将图像缓存在磁盘或内存中的实现。基本原则是将可绘制对象存储为File,然后从那里加载它。这是在图像库和此类应用程序中使用的不同技术。一个非常好的教程可以在文档中找到:developer.android.com/training/displaying-bitmaps/…
【解决方案2】:

使用service 将XML 从服务器拉到database。你的activity 会懒惰地从database 加载数据,就像你在 Google Play 中看到的那样。见CWAC EndlessAdapter。也可以看看 Universal Image Loader for Android 用图片填充您的 listview

【讨论】:

    【解决方案3】:

    OutOfMemoryException 很可能是由图像引起的。

    假设您要显示带有图片的酒店列表。您以 XML 格式获取酒店信息并将它们保存在列表(或类似结构)中。您的酒店类可能有一个像 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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多