内存不足的错误,而使用LazyList中的ListView [英] Out Of memory error while using LazyList in ListView
问题描述
可能重复:结果
<一href=\"http://stackoverflow.com/questions/13855413/out-of-memory-error-using-universal-image-loader-and-images-getting-refreshed\">Out使用通用图像装载机和图像内存错误得到刷新
块引用>我一直在关注教程上延迟加载列表视图,比我实现 LazyList 图像。在code是否正常工作按我的要求,但它是在某个阶段给内存不足的错误。我使用ImageLoader的,内存缓存,LazyAdapter,FileChache和utils的同一code。
这里是LazyAdapter类公共类LazyAdapter延伸BaseAdapter { 私人活动活动;
私人的ArrayList&LT;串GT; movieThumbnail;
私人的ArrayList&LT;串GT; movieText;
私有静态LayoutInflater吹气= NULL;
公共ImageLoader的ImageLoader的; 公共LazyAdapter(活动一,ArrayList的&LT;串GT; movieThumbnail,ArrayList的&LT;串GT; movieText){
活性=一个;
/ *数据= D; * /
this.movieThumbnail = movieThumbnail;
this.movieText = movieText;
吹气=(LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ImageLoader的=新ImageLoader的(activity.getApplicationContext());
} 公众诠释的getCount(){
返回movieText.size();
} 公共对象的getItem(INT位置){
返回的位置;
} 众长getItemId(INT位置){
返回的位置;
} 公共查看getView(INT位置,查看convertView,父母的ViewGroup){
查看VI = convertView;
如果(convertView == NULL)
VI = inflater.inflate(R.layout.listrow,NULL); TextView的文本=(TextView的)vi.findViewById(R.id.rowListTextView);
ImageView的图像=(ImageView的)vi.findViewById(R.id.movieImage);
text.setText(movieText.get(位置));
imageLoader.DisplayImage(movieThumbnail.get(位置),图像);
返回VI;
}
}的MemoryCache
公共类的MemoryCache { 私有静态最后弦乐TAG =的MemoryCache;
私人地图&LT;弦乐,位图&GT;缓存= Collections.synchronizedMap(
新的LinkedHashMap&LT;弦乐,位图&GT;(10,1.5f,真实)); //最后一个参数如此LRU排序
私人长期的大小= 0; //电流分配的大小
私人长期限制= 1000000;以字节为单位//最大内存 公众的MemoryCache(){
//使用可用堆大小的25%
setLimit(调用Runtime.getRuntime()maxMemory()/ 6);
} 公共无效setLimit(长NEW_LIMIT){
极限= NEW_LIMIT;
Log.i(TAG的MemoryCache会使用到限+ / 1024/1024 +MB);
} 公共位图的get(字符串ID){
尝试{
如果(!cache.containsKey(ID))
返回null;
// NullPointerException异常有时会发生在这里的http://$c$c.google.com/p/osmdroid/issues/detail ID = 78
返回cache.get(ID);
}赶上(NullPointerException异常前){
ex.printStackTrace();
返回null;
}
} 公共无效认沽(字符串ID,位图位图){
尝试{
如果(cache.containsKey(ID))
大小 - = getSizeInBytes(cache.get(ID));
cache.put(ID,位图);
大小+ = getSizeInBytes(位图);
checkSize();
}赶上(的Throwable日){
th.printStackTrace();
}
} 私人无效checkSize(){
Log.i(TAG,高速缓存大小=+尺寸+长度=+ cache.size());
如果(大小&GT;限制){
迭代器&LT;钥匙进入LT;弦乐,位图&GT;&GT; ITER = cache.entrySet()迭代器(); //最近最少访问的项目将是第一个迭代
而(iter.hasNext()){
进入&LT;弦乐,位图&GT;条目= iter.next();
大小 - = getSizeInBytes(entry.getValue());
iter.remove();
如果(大小&LT; =极限)
打破;
}
Log.i(TAG,清洁缓存新的大小。+ cache.size());
}
} 公共无效清除(){
尝试{
// NullPointerException异常有时会发生在这里的http://$c$c.google.com/p/osmdroid/issues/detail ID = 78
cache.clear();
大小= 0;
}赶上(NullPointerException异常前){
ex.printStackTrace();
}
} 长getSizeInBytes(位图位图){
如果(位图== NULL)
返回0;
返回bitmap.getRowBytes()* bitmap.getHeight();
}
}ImageLoade类
公共类ImageLoader的{ 的MemoryCache的MemoryCache =新的MemoryCache();
FileCache fileCache;
私人地图&LT; ImageView的,字符串&GT; imageViews = Collections.synchronizedMap(新的WeakHashMap&LT; ImageView的,字符串&GT;());
ExecutorService的ExecutorService的;
处理程序处理程序=新的处理程序(); //处理程序,以显示在UI线程图片 公共ImageLoader的(上下文的背景下){
fileCache =新FileCache(背景);
ExecutorService的= Executors.newFixedThreadPool(5);
} 最终诠释stub_id = R.drawable.ic_launcher;
公共无效DisplayImage(字符串URL,ImageView的ImageView的)
{
imageViews.put(ImageView的,URL);
位图位图= memoryCache.get(URL);
如果(位图!= NULL)
imageView.setImageBitmap(位图);
其他
{
queuePhoto(URL,ImageView的);
imageView.setImageResource(stub_id);
}
} 私人无效queuePhoto(字符串URL,ImageView的ImageView的)
{
PhotoToLoad P =新PhotoToLoad(URL,ImageView的);
executorService.submit(新PhotosLoader(P));
} 私人位图getBitmap(字符串URL)
{
文件F = fileCache.getFile(URL); //从SD缓存
位图B =去codeFILE(F);
如果(B!= NULL) 返回b; //从网页
尝试{
位图位图= NULL;
URL =图片网址新的URL(网址);
HttpURLConnection的康恩=(HttpURLConnection类)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(真);
InputStream为= conn.getInputStream();
OutputStream的OS =新的FileOutputStream(F);
Utils.CopyStream(是,OS);
os.close();
/ *位=去codeFILE(F); * /
返回位图;
}赶上(Throwable的前){
ex.printStackTrace();
如果(前的instanceof的OutOfMemoryError)
memoryCache.clear();
返回null;
}
} //德$ C $连拍影像的鳞它来减少内存消耗
私人位图德codeFILE(文件f){
尝试{
//德code图像尺寸
BitmapFactory.Options O =新BitmapFactory.Options();
o.inJustDe codeBounds = TRUE;
的FileInputStream流1 =新的FileInputStream(F);
BitmapFactory.de codeStream(STREAM1,空,O);
stream1.close(); //找到正确的比例值。它应该是2的幂。
最终诠释REQUIRED_SIZE = 70;
INT width_tmp = o.outWidth,height_tmp = o.outHeight;
int标= 1;
而(真){
如果(width_tmp / 2'; REQUIRED_SIZE || height_tmp / 2版; REQUIRED_SIZE)
打破;
width_tmp / = 2;
height_tmp / = 2;
规模* = 2;
} //德code。与inSampleSize
BitmapFactory.Options O2 =新BitmapFactory.Options();
o2.inSampleSize =规模;
流2的FileInputStream =新的FileInputStream(F);
位图位图= BitmapFactory.de codeStream(流2,空,O2);
stream2.close();
返回位图;
}赶上(FileNotFoundException异常五){
}
赶上(IOException异常五){
e.printStackTrace();
}
返回null;
} //任务队列
私有类PhotoToLoad
{
公共字符串的URL;
公共ImageView的ImageView的;
公共PhotoToLoad(字符串U,ImageView的我){
URL = U;
ImageView的= I;
}
} 类PhotosLoader实现Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad){
this.photoToLoad = photoToLoad;
} @覆盖
公共无效的run(){
尝试{
如果(imageViewReused(photoToLoad))
返回;
BMP位图= getBitmap(photoToLoad.url);
memoryCache.put(photoToLoad.url,BMP);
如果(imageViewReused(photoToLoad))
返回;
BitmapDisplayer BD =新BitmapDisplayer(BMP,photoToLoad);
handler.post(BD);
}赶上(的Throwable日){
th.printStackTrace();
}
}
} 布尔imageViewReused(PhotoToLoad photoToLoad){
字符串标记= imageViews.get(photoToLoad.imageView);
如果(标记== NULL ||!tag.equals(photoToLoad.url))
返回true;
返回false;
} //用在UI线程来显示位图
类BitmapDisplayer实现Runnable
{
位图位图;
PhotoToLoad photoToLoad;
公共BitmapDisplayer(位图B,PhotoToLoad P){位= B; photoToLoad = P;}
公共无效的run()
{
如果(imageViewReused(photoToLoad))
返回;
如果(位图!= NULL)
photoToLoad.imageView.setImageBitmap(位图);
其他
photoToLoad.imageView.setImageResource(stub_id);
} } 公共无效clearCache(){
memoryCache.clear();
fileCache.clear();
}}
解决方案使用此方法图像加载这是当你使用滚动比力关闭不要创建问题
MainClassActivity:
ArrayList的&LT; NewsItems&GT;新闻=新的ArrayList&LT; NewsItems&GT;();
SetListView站;
STA =新SetListView(MainActivity.this,新闻);
lv.setAdapter(STA); 对于(NewsItems小号:新闻){
s.loadImage(STA);
}
公共类SetListView延伸BaseAdapter {
私人LayoutInflater吹气= NULL;
活动活动;
ArrayList的&LT; NewsItems&GT;一;
公共SetListView(活动一,ArrayList的&LT; NewsItems - 酮)
{
this.activity =一个;
吹气=(LayoutInflater)a.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.one =之一;
} @覆盖
公众诠释的getCount(){
返回one.size();
} @覆盖
公共对象的getItem(INT位置){
返回的位置;
} @覆盖
众长getItemId(INT位置){
返回的位置;
} @覆盖
公共查看getView(INT位置,查看convertView,父母的ViewGroup){
查看VI = convertView;
如果(convertView == NULL)
VI = inflater.inflate(R.layout.main1,NULL);
TextView的TV1 =(TextView中)vi.findViewById(R.id.textView1);
TextView中TV2 =(TextView中)vi.findViewById(R.id.textView2);
tv1.setText(one.get(位置).get_title());
tv2.setText(one.get(位置).get_pudDate());
//位图BM = loadBitmap(one.get(位置).get_image());
如果(one.get(位置).get_bm()!= NULL)
((ImageView的)vi.findViewById(R.id.imageView1))setImageBitmap(one.get(位置).get_bm());
其他
((ImageView的)vi.findViewById(R.id.imageView1))setImageResource(R.drawable.ic_launcher)。
返回VI;
} }
包com.dudhat.classes;进口java.io.BufferedInputStream中;
进口java.io.IOException异常;
进口的java.io.InputStream;
进口的java.net.URL;
进口java.net.URLConnection中;进口com.dudhat.rssfeeds.SetListView;进口android.graphics.Bitmap;
进口android.graphics.BitmapFactory;
进口android.os.AsyncTask;
进口android.util.Log;公共类NewsItems {
私人SetListView站;
串_title,_pudDate,_description,_image;
位图_bm; 公共位图get_bm(){
返回_bm;
} 公共字符串get_image(){
返回_image;
} 公共字符串get_title(){
返回_title;
} 公共字符串get_pudDate(){
返回_pudDate;
} 公共字符串get_description(){
返回_description;
}
公共SetListView getAdapter(){
返回站;
} 公共无效setAdapter(SetListView STA){
this.sta =站;
}
公共NewsItems(字符串_title,字符串_pubdate,字符串_description,字符串_image,位图_bm)
{
this._description = _description;
this._pudDate = _pubdate;
this._title = _title;
this._image = _image;
this._bm = _bm;
}
公共无效的LoadImage(SetListView STA){
this.sta =站;
如果(_image =空&放大器;!&放大器;!_image.equals()){
新ImageLoadTask()执行(_image);
}
}
私有类ImageLoadTask扩展的AsyncTask&LT;字符串,字符串,位图&GT; { @覆盖
在preExecute保护无效(){
Log.i(ImageLoadTask,导入图像...);
} 保护位图doInBackground(字符串参数...){
Log.i(ImageLoadTask,试图加载图像URL:+参数[0]);
尝试{
位图B = loadBitmap(参数[0]);
返回b;
}赶上(例外五){
e.printStackTrace();
返回null;
}
}
保护无效onPostExecute(位图RET){
如果(RET!= NULL){
_bm = RET;
如果(STA!= NULL){
sta.notifyDataSetChanged();
}
}其他{
}
}
}
公共位图loadBitmap(字符串URL)
{
位图BM = NULL;
InputStream为= NULL;
二BufferedInputStream为= NULL;
尝试
{
康涅狄格州的URLConnection =新的URL(网址).openConnection();
conn.connect();
是= conn.getInputStream();
双=新的BufferedInputStream(是,8192);
BM = BitmapFactory.de codeStream(之二);
}
赶上(例外五)
{
e.printStackTrace();
}
最后{
如果(之二!= NULL)
{
尝试
{
bis.close();
}
赶上(IOException异常E)
{
e.printStackTrace();
}
}
如果(是!= NULL)
{
尝试
{
is.close();
}
赶上(IOException异常E)
{
e.printStackTrace();
}
}
}
返回BM;
}
}Possible Duplicate:
Out Of memory error using Universal Image Loader and images getting refreshedI have been following the Tutorials on lazy loading the images in a list view and than I implemented LazyList . The code is working properly as per my requirements however it is giving Out Of Memory Errors at some stages. I am using the same code of ImageLoader, Memory cache, LazyAdapter, FileChache and Utils. Here is LazyAdapter class
public class LazyAdapter extends BaseAdapter { private Activity activity; private ArrayList<String> movieThumbnail; private ArrayList<String> movieText; private static LayoutInflater inflater=null; public ImageLoader imageLoader; public LazyAdapter(Activity a, ArrayList<String> movieThumbnail, ArrayList<String> movieText) { activity = a; /*data=d;*/ this.movieThumbnail = movieThumbnail; this.movieText = movieText; inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); imageLoader=new ImageLoader(activity.getApplicationContext()); } public int getCount() { return movieText.size(); } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { View vi=convertView; if(convertView==null) vi = inflater.inflate(R.layout.listrow, null); TextView text=(TextView)vi.findViewById(R.id.rowListTextView); ImageView image=(ImageView)vi.findViewById(R.id.movieImage); text.setText(movieText.get(position)); imageLoader.DisplayImage(movieThumbnail.get(position), image); return vi; } }
MemoryCache
public class MemoryCache { private static final String TAG = "MemoryCache"; private Map<String, Bitmap> cache=Collections.synchronizedMap( new LinkedHashMap<String, Bitmap>(10,1.5f,true));//Last argument true for LRU ordering private long size=0;//current allocated size private long limit=1000000;//max memory in bytes public MemoryCache(){ //use 25% of available heap size setLimit(Runtime.getRuntime().maxMemory()/6); } public void setLimit(long new_limit){ limit=new_limit; Log.i(TAG, "MemoryCache will use up to "+limit/1024./1024.+"MB"); } public Bitmap get(String id){ try{ if(!cache.containsKey(id)) return null; //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 return cache.get(id); }catch(NullPointerException ex){ ex.printStackTrace(); return null; } } public void put(String id, Bitmap bitmap){ try{ if(cache.containsKey(id)) size-=getSizeInBytes(cache.get(id)); cache.put(id, bitmap); size+=getSizeInBytes(bitmap); checkSize(); }catch(Throwable th){ th.printStackTrace(); } } private void checkSize() { Log.i(TAG, "cache size="+size+" length="+cache.size()); if(size>limit){ Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iterated while(iter.hasNext()){ Entry<String, Bitmap> entry=iter.next(); size-=getSizeInBytes(entry.getValue()); iter.remove(); if(size<=limit) break; } Log.i(TAG, "Clean cache. New size "+cache.size()); } } public void clear() { try{ //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 cache.clear(); size=0; }catch(NullPointerException ex){ ex.printStackTrace(); } } long getSizeInBytes(Bitmap bitmap) { if(bitmap==null) return 0; return bitmap.getRowBytes() * bitmap.getHeight(); } }
ImageLoade class
public class ImageLoader { MemoryCache memoryCache=new MemoryCache(); FileCache fileCache; private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); ExecutorService executorService; Handler handler=new Handler();//handler to display images in UI thread public ImageLoader(Context context){ fileCache=new FileCache(context); executorService=Executors.newFixedThreadPool(5); } final int stub_id=R.drawable.ic_launcher; public void DisplayImage(String url, ImageView imageView) { imageViews.put(imageView, url); Bitmap bitmap=memoryCache.get(url); if(bitmap!=null) imageView.setImageBitmap(bitmap); else { queuePhoto(url, imageView); imageView.setImageResource(stub_id); } } private void queuePhoto(String url, ImageView imageView) { PhotoToLoad p=new PhotoToLoad(url, imageView); executorService.submit(new PhotosLoader(p)); } private Bitmap getBitmap(String url) { File f=fileCache.getFile(url); //from SD cache Bitmap b = decodeFile(f); if(b!=null) return b; //from web try { Bitmap bitmap=null; URL imageUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); conn.setConnectTimeout(30000); conn.setReadTimeout(30000); conn.setInstanceFollowRedirects(true); InputStream is=conn.getInputStream(); OutputStream os = new FileOutputStream(f); Utils.CopyStream(is, os); os.close(); /* bitmap = decodeFile(f);*/ return bitmap; } catch (Throwable ex){ ex.printStackTrace(); if(ex instanceof OutOfMemoryError) memoryCache.clear(); return null; } } //decodes image and scales it to reduce memory consumption private Bitmap decodeFile(File f){ try { //decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; FileInputStream stream1=new FileInputStream(f); BitmapFactory.decodeStream(stream1,null,o); stream1.close(); //Find the correct scale value. It should be the power of 2. final int REQUIRED_SIZE=70; int width_tmp=o.outWidth, height_tmp=o.outHeight; int scale=1; while(true){ if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE) break; width_tmp/=2; height_tmp/=2; scale*=2; } //decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize=scale; FileInputStream stream2=new FileInputStream(f); Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2); stream2.close(); return bitmap; } catch (FileNotFoundException e) { } catch (IOException e) { e.printStackTrace(); } return null; } //Task for the queue private class PhotoToLoad { public String url; public ImageView imageView; public PhotoToLoad(String u, ImageView i){ url=u; imageView=i; } } class PhotosLoader implements Runnable { PhotoToLoad photoToLoad; PhotosLoader(PhotoToLoad photoToLoad){ this.photoToLoad=photoToLoad; } @Override public void run() { try{ if(imageViewReused(photoToLoad)) return; Bitmap bmp=getBitmap(photoToLoad.url); memoryCache.put(photoToLoad.url, bmp); if(imageViewReused(photoToLoad)) return; BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad); handler.post(bd); }catch(Throwable th){ th.printStackTrace(); } } } boolean imageViewReused(PhotoToLoad photoToLoad){ String tag=imageViews.get(photoToLoad.imageView); if(tag==null || !tag.equals(photoToLoad.url)) return true; return false; } //Used to display bitmap in the UI thread class BitmapDisplayer implements Runnable { Bitmap bitmap; PhotoToLoad photoToLoad; public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;} public void run() { if(imageViewReused(photoToLoad)) return; if(bitmap!=null) photoToLoad.imageView.setImageBitmap(bitmap); else photoToLoad.imageView.setImageResource(stub_id); } } public void clearCache() { memoryCache.clear(); fileCache.clear(); } }
解决方案use this method to Image load This is dont create problem when you use scrolling than force to close
MainClassActivity: ArrayList<NewsItems> news = new ArrayList<NewsItems>(); SetListView sta; sta = new SetListView(MainActivity.this, news); lv.setAdapter(sta); for (NewsItems s : news) { s.loadImage(sta); } public class SetListView extends BaseAdapter{ private LayoutInflater inflater = null; Activity activity; ArrayList<NewsItems> one; public SetListView(Activity a,ArrayList<NewsItems> one) { this.activity = a; inflater = (LayoutInflater) a.getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.one = one; } @Override public int getCount() { return one.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View vi = convertView; if (convertView == null) vi = inflater.inflate(R.layout.main1, null); TextView tv1 = (TextView) vi.findViewById(R.id.textView1); TextView tv2 = (TextView) vi.findViewById(R.id.textView2); tv1.setText(one.get(position).get_title()); tv2.setText(one.get(position).get_pudDate()); // Bitmap bm = loadBitmap(one.get(position).get_image()); if(one.get(position).get_bm() != null) ((ImageView)vi.findViewById(R.id.imageView1)).setImageBitmap(one.get(position).get_bm()); else ((ImageView)vi.findViewById(R.id.imageView1)).setImageResource(R.drawable.ic_launcher); return vi; } } package com.dudhat.classes; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import com.dudhat.rssfeeds.SetListView; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.util.Log; public class NewsItems { private SetListView sta; String _title,_pudDate,_description,_image; Bitmap _bm; public Bitmap get_bm() { return _bm; } public String get_image() { return _image; } public String get_title() { return _title; } public String get_pudDate() { return _pudDate; } public String get_description() { return _description; } public SetListView getAdapter() { return sta; } public void setAdapter(SetListView sta) { this.sta = sta; } public NewsItems(String _title,String _pubdate,String _description,String _image,Bitmap _bm) { this._description = _description; this._pudDate = _pubdate; this._title = _title; this._image = _image; this._bm = _bm; } public void loadImage(SetListView sta) { this.sta = sta; if (_image != null && !_image.equals("")) { new ImageLoadTask().execute(_image); } } private class ImageLoadTask extends AsyncTask<String, String, Bitmap> { @Override protected void onPreExecute() { Log.i("ImageLoadTask", "Loading image..."); } protected Bitmap doInBackground(String... param) { Log.i("ImageLoadTask", "Attempting to load image URL: " + param[0]); try { Bitmap b = loadBitmap(param[0]); return b; } catch (Exception e) { e.printStackTrace(); return null; } } protected void onPostExecute(Bitmap ret) { if (ret != null) { _bm = ret; if (sta != null) { sta.notifyDataSetChanged(); } } else { } } } public Bitmap loadBitmap(String url) { Bitmap bm = null; InputStream is = null; BufferedInputStream bis = null; try { URLConnection conn = new URL(url).openConnection(); conn.connect(); is = conn.getInputStream(); bis = new BufferedInputStream(is, 8192); bm = BitmapFactory.decodeStream(bis); } catch (Exception e) { e.printStackTrace(); } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return bm; } }
这篇关于内存不足的错误,而使用LazyList中的ListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!