我现在试图找出很长时间的原因,为什么我在listView的视图中得到了此内存泄漏。
奇怪的部分是,将图像视图(coveriv)设置为((bitmapdrable)_activity.resources.getDrawable(resource.drawable.splash))。位图,根本没有问题。
当我使用等待ImageLoader.decodesampledbitmapmapfromresourceasync(localimagelocation,imgwidth,imgheight)时,每次我在ListView
中滚动时都会有一个巨大的内存泄漏我尝试使用内存分析仪工具找到参考,但没有……尽管Mat说问题是位图
public void ImageLoaded(string localImageLocation)
{
int screenWidth = _activity.Resources.DisplayMetrics.WidthPixels;
int imgWidth = screenWidth - (int)ConvertDpToPix (32f);
int imgHeight = (int)(ConvertDpToPix(206f));
BundleProgress.Visibility = ViewStates.Gone;
if (CoverIv.Drawable != null)
{
((BitmapDrawable)CoverIv.Drawable).Bitmap.Recycle ();
((BitmapDrawable)CoverIv.Drawable).Bitmap.Dispose ();
CoverIv.SetImageDrawable (null);
}
CoverIv.SetImageBitmap
(
//MEMORYLEAK: await ImageLoader.DecodeSampledBitmapFromResourceAsync (localImageLocation, imgWidth, imgHeight)
((BitmapDrawable)_activity.Resources.GetDrawable(Resource.Drawable.splash)).Bitmap
);
Imageloader类中的方法:
public static async Task<Bitmap> DecodeSampledBitmapFromResourceAsync (String path,int reqWidth, int reqHeight)
{
// First decode with inJustDecodeBounds=true to check dimensions of the image
BitmapFactory.Options options = new BitmapFactory.Options();
options.InJustDecodeBounds = true;
Bitmap bitmap = await BitmapFactory.DecodeFileAsync(path, options);
// Calculate inSampleSize
options.InSampleSize = CalculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
options.InPreferredConfig = Bitmap.Config.Argb8888;
//options.InDither = true;
return await BitmapFactory.DecodeFileAsync(path, options);
}
public static int CalculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
float height = options.OutHeight;
float width = options.OutWidth;
double inSampleSize = 1D;
if (height > reqHeight || width > reqWidth)
{
int halfHeight = (int)(height / 2);
int halfWidth = (int)(width / 2);
// Calculate a inSampleSize that is a power of 2 - the decoder will use a value that is a power of two anyway.
while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth)
{
inSampleSize *= 2;
}
}
return (int)inSampleSize;
}
适配器:
public override View GetView (int position, View convertView, ViewGroup parent)
{
BaseBundelVO bundle = _bundles [position];
DSBundleListItem bundleHolder = null;
DSBundleArchiveItem archiveHolder = null;
int type = GetItemViewType(position);
if (convertView == null)
{
bundleHolder = new DSBundleListItem (_activity.ApplicationContext);
archiveHolder = new DSBundleArchiveItem (_activity.ApplicationContext);
switch (type)
{
case 0:
convertView = _activity.LayoutInflater.Inflate (Resource.Layout.dsBundleListItem, null);
bundleHolder.IconIv = convertView.FindViewById<ImageView> (Resource.Id.iconIv);
bundleHolder.CoverIv = convertView.FindViewById<ImageView> (Resource.Id.coverIv);
bundleHolder.CoverTitleTv = convertView.FindViewById<TextView> (Resource.Id.coverTitleTv);
bundleHolder.CoverSubTitleTv = convertView.FindViewById<TextView> (Resource.Id.coverSubTitleTv);
bundleHolder.BundleProgress = convertView.FindViewById<ProgressBar> (Resource.Id.bundleProgress);
convertView.Tag = bundleHolder;
break;
case 1:
convertView = _activity.LayoutInflater.Inflate (Resource.Layout.dsBundleArchiveItem, null);
archiveHolder.ArchiveTitleTv = convertView.FindViewById<TextView> (Resource.Id.archiveTitleTv);
archiveHolder.ArchiveSubTitleTv = convertView.FindViewById<TextView> (Resource.Id.archiveSubTitleTv);
convertView.Tag = archiveHolder;
break;
}
}
else
{
switch (type)
{
case 0:
bundleHolder = (DSBundleListItem)convertView.Tag;
break;
case 1:
archiveHolder = (DSBundleArchiveItem)convertView.Tag;
break;
}
}
switch (type)
{
case 0:
bundleHolder.CoverTitleTv.Text = bundle.Title;
bundleHolder.CoverSubTitleTv.Text = bundle.SubTitle;
bundleHolder.CoverIv.SetImageDrawable (null);
bundleHolder.IconIv.SetImageDrawable (null);
bundleHolder.LoadImage(bundle.CoverImageLocation,bundle.Icon);
break;
case 1:
archiveHolder.ArchiveTitleTv.Text = "Archief";
archiveHolder.ArchiveSubTitleTv.Text = "Bekijk onze eerder verschenen publicaties";
break;
}
return convertView;
}
public void SetData(List<BaseBundelVO> bundles)
{
_bundles.Clear ();
_bundles.AddRange(bundles);
}
使用图像时使用毕加索库,它起作用了!
我也推荐Pisasso库。这是链接:http://square.github.io/picasso/
它立即从网络中检索图像并在本地缓存。
导入毕加索库后,您必须简单地将此行添加到您的代码中:
Picasso.with(context).load("*your url*").into(*your image view*);
您也可以加载本地图像!
Picasso.with(context).load("file:///android_asset/image.png").into(*your image view*);
希望这会有所帮助,
请尝试我的代码。我认为您的解码有问题:
private Bitmap DisplayRotatedPhoto(Uri path) {
String filePath = path.toString().substring(8);
Bitmap oriented = null;
BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();
bitmapFactoryOptions.inJustDecodeBounds = true;
int REQUIRED_SIZE = 100;
int width_tmp = bitmapFactoryOptions.outWidth, height_tmp = bitmapFactoryOptions.outHeight;
int scale = 2;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
BitmapFactory.Options bitmapFactoryOptions2 = new BitmapFactory.Options();
bitmapFactoryOptions2.inSampleSize = scale;
Bitmap bmp = BitmapFactory.decodeFile(filePath, bitmapFactoryOptions2);
}