我正在做一個有listview的活動。列表視圖是從服務器拉出的大型XML填充的。 我的場景通常是有一個SAX解析器,解析XML並向解析數據返回一個Vector(或類似結構)。 問題是,xml太大,Vector有太多導致內存不足錯誤的元素。 此外,XML有鏈接到正在下載的圖像,這使情況更糟糕。從大型XML填充ListView
在這種情況下應如何管理內存?我在想如果我只能在用戶滾動到列表視圖中的某一行時才加載圖像。
我正在做一個有listview的活動。列表視圖是從服務器拉出的大型XML填充的。 我的場景通常是有一個SAX解析器,解析XML並向解析數據返回一個Vector(或類似結構)。 問題是,xml太大,Vector有太多導致內存不足錯誤的元素。 此外,XML有鏈接到正在下載的圖像,這使情況更糟糕。從大型XML填充ListView
在這種情況下應如何管理內存?我在想如果我只能在用戶滾動到列表視圖中的某一行時才加載圖像。
內存不足異常的問題是加載圖像。 Adapter
在填充ListView
時應該沒有問題。
在一個商業應用程序中,我加載了一個ListView
,每行有9000個記錄,其中有2個TextView
s。所以我猜數據的大小不應該是一個問題。使用AsyncTask
從服務器獲取數據。在doInBackground()
方法中解析和填充適配器,然後在onPostExecute()
中將適配器設置爲ListView
。首先儘量不要包含任何圖像,以確保數據大小不成問題。
如果ListView
加載正確,然後嘗試找到填充圖像的方法。執行此操作有多種方法。如果圖像一遍又一遍地重複,則應該嘗試「緩存內存」實現,否則可能從後臺線程「延遲加載」應該很好地完成這項工作。
編輯:
這是關於如何從後臺線程lazyload圖片非常好的職位/教程。當您查看GridView
中的所有應用程序時,它幾乎與Android市場使用的技術相同,最初有一些灰色圖標,然後突然顯示應用程序的圖像。這是通過後臺線程完成的,當用戶看到確切的行時,後臺線程從互聯網獲取它,填充列表並將其緩存到內存中,以便隨時可用。 Lazy load of images in ListView
你是絕對正確的。什麼是懶加載技巧?如何知道何時從它的url加載給定的圖像?我想在列表視圖中的行可見時加載它,即用戶滾動到它。 – 2012-07-23 08:01:46
我編輯了我的帖子 – 10s 2012-07-23 08:24:33
再次感謝我只是嘗試了一些東西 - 我創建了一個自定義適配器,並實現了getView,我有一個ImageView。我只是在調用getView時啓動了一個AsyncTask,它運行良好,並且滾動是平滑的,但問題是當我再次向上滾動時,圖像再次加載。如果listview以某種方式緩存它會更好。這可能嗎?我認爲使用我的數據結構來保存加載的位圖不是一個好主意,因爲我會再次遇到內存問題。 – 2012-07-23 08:30:02
使用service
將XML從服務器拉到database
。您的activity
比您在Google Play中看到的延遲加載database
的數據要快得多。請參閱CWAC EndlessAdapter。另請參閱 Universal Image Loader for Android填寫您的listview
圖像。
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。
我認爲首先解析數組或ArrayList中的XMl和解析數據存儲..然後在listview ..中綁定數據併爲圖像使用lazyloading .. – 2012-07-23 07:44:29
我實現了一個CursorAdapter,它在bindView期間從文件加載圖像縮略圖(文件名被緩存在數據庫中)。 – Sparky 2012-07-23 07:48:07
使用BaseAdapter可以將圖像設置爲延遲加載。 (關於大的xml,多大?你的意思是你從內存太多的對象列表中脫離內存?) – 2012-07-23 07:49:52