3

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

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

4

3 回答 3

2

内存不足异常的问题是图像的加载。将Adapter自己填充到ListView.

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

使用 anAsyncTask从服务器获取数据。在方法中解析并填充适配器,doInBackground()然后onPostExecute()ListView. 首先尝试不包含任何图像,以确保数据大小不是问题。

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

编辑:

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

于 2012-07-23T07:55:49.393 回答
0

用于service将 XML 从服务器拉到database. 您比在 Google Play 中看到的activity延迟加载数据。database请参阅CWAC EndlessAdapter。另请参阅 适用于 Android 的 Universal Image Loader以填充您listview的图像。

于 2012-07-23T07:50:29.617 回答
0

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。

于 2012-07-23T08:21:09.493 回答