2012-07-23 116 views
3

我正在做一個有listview的活動。列表視圖是從服務器拉出的大型XML填充的。 我的場景通常是有一個SAX解析器,解析XML並向解析數據返回一個Vector(或類似結構)。 問題是,xml太大,Vector有太多導致內存不足錯誤的元素。 此外,XML有鏈接到正在下載的圖像,這使情況更糟糕。從大型XML填充ListView

在這種情況下應如何管理內存?我在想如果我只能在用戶滾動到列表視圖中的某一行時才加載圖像。

+0

我認爲首先解析數組或ArrayList中的XMl和解析數據存儲..然後在listview ..中綁定數據併爲圖像使用lazyloading .. – 2012-07-23 07:44:29

+0

我實現了一個CursorAdapter,它在bindView期間從文件加載圖像縮略圖(文件名被緩存在數據庫中)。 – Sparky 2012-07-23 07:48:07

+1

使用BaseAdapter可以將圖像設置爲延遲加載。 (關於大的xml,多大?你的意思是你從內存太多的對象列表中脫離內存?) – 2012-07-23 07:49:52

回答

2

內存不足異常的問題是加載圖像。 Adapter在填充ListView時應該沒有問題。

在一個商業應用程序中,我加載了一個ListView,每行有9000個記錄,其中有2個TextView s。所以我猜數據的大小不應該是一個問題。使用AsyncTask從服務器獲取數據。在doInBackground()方法中解析和填充適配器,然後在onPostExecute()中將適配器設置爲ListView。首先儘量不要包含任何圖像,以確保數據大小不成問題。

如果ListView加載正確,然後嘗試找到填充圖像的方法。執行此操作有多種方法。如果圖像一遍又一遍地重複,則應該嘗試「緩存內存」實現,否則可能從後臺線程「延遲加載」應該很好地完成這項工作。

編輯:

這是關於如何從後臺線程lazyload圖片非常好的職位/教程。當您查看GridView中的所有應用程序時,它幾乎與Android市場使用的技術相同,最初有一些灰色圖標,然後突然顯示應用程序的圖像。這是通過後臺線程完成的,當用戶看到確切的行時,後臺線程從互聯網獲取它,填充列表並將其緩存到內存中,以便隨時可用。 Lazy load of images in ListView

+0

你是絕對正確的。什麼是懶加載技巧?如何知道何時從它的url加載給定的圖像?我想在列表視圖中的行可見時加載它,即用戶滾動到它。 – 2012-07-23 08:01:46

+0

我編輯了我的帖子 – 10s 2012-07-23 08:24:33

+0

再次感謝我只是嘗試了一些東西 - 我創建了一個自定義適配器,並實現了getView,我有一個ImageView。我只是在調用getView時啓動了一個AsyncTask,它運行良好,並且滾動是平滑的,但問題是當我再次向上滾動時,圖像再次加載。如果listview以某種方式緩存它會更好。這可能嗎?我認爲使用我的數據結構來保存加載的位圖不是一個好主意,因爲我會再次遇到內存問題。 – 2012-07-23 08:30:02

0

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

假設您想顯示帶圖片的酒店列表。您以XML格式獲取酒店信息並將其保存在列表(或類似結構)中。您的酒店班級可能有像URL pictureURL之類的會員和WeakReference<Drawable> picture之類的會員,直到需要時爲空。

您可以讓列表適配器啓動AsyncTask以在getView()方法中下載圖像(如果圖像指向null)並將其設置爲列表中的ImageView和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。