内存泄漏问题始终是Java的问题。我了解您的代码,代码简单的imagecache工具。检查SampleSize值,并且执行程序服务仅在一个线程上运行。四个线程有很大的内存,并且此后台线程有作用。您的“处理程序”交换为“ runOnUIThread”
您应使用;
我的应用程序中发生内存泄漏,这多次触发GC并导致性能问题。我使用leak suspect report
生成了MAT
。这是报告:
问题嫌疑人1:由“”加载的“ android.graphics.Bitmap”的一个实例占用4,194,368(20.13%)字节。内存在由“”加载的“ byte []”的一个实例中累积。 问题嫌疑人2:
问题嫌疑人3:由“”加载的“ android.graphics.Bitmap”的一个实例占用3,145,792(15.10%)字节。内存在由“”加载的“ byte []”的一个实例中累积。 从报告来看,很明显内存泄漏是由于位图造成的。我进行了很多研究,但无法纠正此泄漏。请帮帮我。我正在使用ImageLoader
类下载和显示位图。要使用此类,我只需调用displayImage()
方法。这是代码:public class ImageLoader {
private static ImageLoader imageLoader;
private int maxNoOfConnections = 4;
FileCache fileCache;
ExecutorService executorService;
HttpURLConnection conn;
InputStream is;
OutputStream os;
PhotosLoader photosLoader;
Handler handler;
Bitmap bitmap;
private ImageLoader(Context context) {
fileCache = new FileCache(context);
executorService = Executors.newFixedThreadPool(maxNoOfConnections);
handler = new Handler();
}
public static ImageLoader getInstance(Context context) {
if (imageLoader == null)
imageLoader = new ImageLoader(context);
return imageLoader;
}
public void displayImage(String url, ProgressBar pBar, ImageView imageView) {
photosLoader = new PhotosLoader(url, imageView, pBar);
executorService.submit(photosLoader);
}
private Bitmap getBitmap(String url) {
File f = fileCache.getFile(url);
bitmap = decodeFile(f);
if (bitmap != null)
return bitmap;
try
{
URL imageUrl = new URL(url);
conn = (HttpURLConnection) imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
is = conn.getInputStream();
os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex)
{
Log.e("inNews", "Image Url Malformed");
return null;
}
}
private Bitmap decodeFile(File f) {
try
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
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;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e)
{
}
return null;
}
class PhotosLoader implements Runnable {
String url;
ImageView imageView;
ProgressBar pBar;
Bitmap bmp;
public PhotosLoader(String url, ImageView imageView, ProgressBar pBar) {
this.url = url;
this.imageView = imageView;
this.pBar = pBar;
}
@Override
public void run() {
bmp = getBitmap(url);
handler.post(new Runnable() {
@Override
public void run() {
if (bmp != null)
{
pBar.setVisibility(View.GONE);
imageView.setImageBitmap(bmp);
} else
{
pBar.setVisibility(View.GONE);
imageView.setImageResource(R.drawable.img_no_image_grid);
}
}
});
}
}
}
[请帮助我纠正我的代码。谢谢!
注意:
我没有使用过bitmap.recycle()
,因为该文档说,蜂窝后GC会收集位图,并且不再需要强行回收它! 我的应用程序中发生内存泄漏,这多次触发GC并导致性能问题。我使用MAT生成了泄漏怀疑报告。这是报告:问题嫌疑人1:一个...
内存泄漏问题始终是Java的问题。我了解您的代码,代码简单的imagecache工具。检查SampleSize值,并且执行程序服务仅在一个线程上运行。四个线程有很大的内存,并且此后台线程有作用。您的“处理程序”交换为“ runOnUIThread”
您应使用;
活动活动
=(活动)imageView.getContext();__activity__.runOnUIThread(new Runnable() { if (bmp != null) { pBar.setVisibility(View.GONE); imageView.setImageBitmap(bmp); } else { pBar.setVisibility(View.GONE); imageView.setImageResource(R.drawable.img_no_image_grid); } });
我认为问题是Singleton实例...我制作了LazyList项目的分支,请检查以下内容:
https://github.com/nicolasjafelle/LazyList
我有相同的内存泄漏,但是,也许我是错的,除非您使用System.exit()终止进程,否则永远不会垃圾收集此单例。
这就是原始LazyList项目不使用Singleton的原因。我还认为,如果您需要缓存,那么对于所有应用程序来说,它都将是快速且相同的。
此ImageLoader中重要的是FileCache和MemoryCache,当您调用clearCache收集的位图时。
我认为答案很简单,当不需要内存时/当OOM出现异常时,只需清除缓存。我为你做了
MemoryCache memoryCache = new MemoryCache(); 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(); conn.disconnect(); bitmap = decodeFile(f); return bitmap; } catch (Throwable ex) { ex.printStackTrace(); if (ex instanceof OutOfMemoryError) memoryCache.clear(); return null; }
当您必须在活动中初始化库时,请始终传递应用程序上下文,而不是活动上下文。
内存泄漏问题始终是Java的问题。我了解您的代码,代码简单的imagecache工具。检查SampleSize值,并且执行程序服务仅在一个线程上运行。四个线程有很大的内存,并且此后台线程有作用。您的“处理程序”交换为“ runOnUIThread”
您应使用;
我认为问题是Singleton实例...我制作了LazyList项目的分支,请检查以下内容:
https://github.com/nicolasjafelle/LazyList
我有相同的内存泄漏,但是,也许我是错的,除非您使用System.exit()终止进程,否则永远不会垃圾收集此单例。
我认为答案很简单,当不需要内存时/当OOM出现异常时,只需清除缓存。我为你做了
MemoryCache memoryCache = new MemoryCache();
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();
conn.disconnect();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex) {
ex.printStackTrace();
if (ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
当您必须在活动中初始化库时,请始终传递应用程序上下文,而不是活动上下文。