我想在滚动回收器视图时异步加载图像。为此我用picasso从网址加载图片。此外,我正在使用图像的圆形图像视图。
现在,当我首先向上和向下滚动时,需要10到12秒才能加载图像。当我滚动它时会在圆形图像视图中显示内存错误。
contactAdapter:
public class ContactAdapter extends RecyclerView.Adapter<FeedListRowHolder> {
private List<FeedItem> feedItemList;
private Context mContext;
public ContactAdapter(Context context, List<FeedItem> feedItemList) {
this.feedItemList = feedItemList;
this.mContext = context;
}
@Override
public FeedListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout,null);
FeedListRowHolder mh = new FeedListRowHolder(v);
return mh;
}
@Override
public void onBindViewHolder(FeedListRowHolder feedListRowHolder, int i) {
final FeedItem feedItem = feedItemList.get(i);
Log.e("Imagename",""+"http://xesoftwares.co.in/contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg");//+feedItem.getThumbnail());
/* Picasso.with(mContext).load("http://xesoftwares.co.in/contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg")
.error(R.drawable.ic_account_circle_black_24dp)
.placeholder(R.drawable.ic_account_circle_black_24dp)
.into(feedListRowHolder.thumbnail)
;*/
Picasso.with(mContext).load("http://xesoftwares.co.in/contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg")
.error(R.drawable.ic_account_circle_black_24dp)
.placeholder(R.drawable.ic_account_circle_black_24dp)
.into(new Target() {
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
try {
String root = Environment.getExternalStorageDirectory().getPath();
File myDir = new File(root +"/Contact");
if (!myDir.exists()) {
myDir.mkdirs();
}
// String name = new Date().toString();
String name = new Date().toString()+".jpg";
File myDir1 = new File(myDir, name);
FileOutputStream out = new FileOutputStream(myDir1);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
ImageFilePath imageFilePath1=new ImageFilePath(myDir1);
ComplexPreferences complexPreferences112 = ComplexPreferences.getComplexPreferences(mContext, "mypref112", Context.MODE_PRIVATE);
complexPreferences112.putObject("imageFilePath1", imageFilePath1);
Log.e("user2", "" + imageFilePath1);
complexPreferences112.commit();
out.flush();
out.close();
} catch(Exception e){
// some action
}
}
public void onBitmapFailed(Drawable errorDrawable) {
}
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
ComplexPreferences complexPreferences112 = ComplexPreferences.getComplexPreferences(mContext, "mypref112", mContext.MODE_PRIVATE);
ImageFilePath imageFilePath1= complexPreferences112.getObject("imageFilePath1", ImageFilePath.class);
File myDir1=imageFilePath1.getprofile();
Picasso.with(mContext).load(myDir1).into(feedListRowHolder.thumbnail);
feedListRowHolder.title.setText(Html.fromHtml(feedItem.getTitle()));
//feedListRowHolder.genre.setText(Html.fromHtml(feedItem.getGenre()));
}
@Override
public int getItemCount() {
return (null != feedItemList ? feedItemList.size() : 0);
}
}
roundedImageView:
public class RoundedImageView extends ImageView {
public RoundedImageView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable)drawable).getBitmap() ;
if(b!=null) {
Bitmap bitmap = b.copy(Config.ARGB_4444, true); //error line 39
int w = getWidth() / 2;
Bitmap roundBitmap = getRoundedCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
}
public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
Bitmap finalBitmap;
if(bitmap.getWidth() != radius || bitmap.getHeight() != radius)
finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius, false);
else
finalBitmap = bitmap;
Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
finalBitmap.getHeight(), Config.ARGB_4444);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, finalBitmap.getWidth(), finalBitmap.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(finalBitmap.getWidth() / 2+0.7f, finalBitmap.getHeight() / 2+0.7f,
finalBitmap.getWidth() / 2+0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(finalBitmap, rect, rect, paint);
return output;
}
}
错误:
java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCopy(Native Method)
at android.graphics.Bitmap.copy(Bitmap.java:556)
at com.xesc.contacts.utils.RoundedImageView.onDraw(RoundedImageView.java:39)
如何解决内存不足错误?我试图在毕加索中使用.fit(),但它给出了illegalSateException。加载图像至少需要10秒钟,如何减少加载图像的时间?
谢谢..
编辑:.into()之后的代码不起作用,它直接跳转到complexShared首选项。并且由于复杂的sharedPreferences保持为null,因此抛出空指针异常。
当我卸载应用程序并再次运行时,就会发生这种情况。在它运行良好之前。
答案 0 :(得分:0)
首先检查::如果下载的图像有大流,它将导致outofmemory:所以首先执行此操作
Picasso.with(mContext).load("http://xesoftwares.co.in /contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg")
.error(R.drawable.ic_account_circle_black_24dp)
.placeholder(R.drawable.ic_account_circle_black_24dp)
.resize(width, height) //you height width
下一步检查::压缩到bitmap ::将try catch中的压缩作为危险代码:让我知道它是否有帮助:)
编辑:为空指针执行此解决方案
ImageFilePath imageFilePath1=new ImageFilePath(myDir1);
ComplexPreferences complexPreferences112 = ComplexPreferences.getComplexPreferences(mContext, "mypref112", Context.MODE_PRIVATE);
if(imageFilePath1!=null)
complexPreferences112.putObject("imageFilePath1", imageFilePath1);
答案 1 :(得分:0)
您的代码可能会将完整图像下载到内存中,在内存中您不需要完整图像,它可能更接近您的图像视图,
在picaso fit()
处理程序中,它在BitmapFactory.Options上使用inSampleSize在图像被加载到内存时对其进行下采样,但它取决于你的图像视图大小,
它可能对你有所帮助。
您可以使用:
.fit().centerCrop()
答案 2 :(得分:0)
查看您的代码,您不会回收位图,因此预计会出现OutOfMemory错误,一旦您不使用它们,您需要回收所有位图,因此您必须继续对它们进行引用。请在此处了解有关回收位图的更深入见解:
Android: Bitmap recycle() how does it work?
在你的情况下,你的ImageView中的onDraw()函数,你创建2个位图,一个带有副本,一个带有裁剪:
首先,您不需要创建位图,在这里您可以在不创建实际位图的情况下读取图像大小,因此如果图像很大,您将会崩溃:
android: get image dimensions without opening it
public static Bitmap lessResolution (String filePath, int width, int height) {
int reqHeight = height;
int reqWidth = width;
BitmapFactory.Options options = new BitmapFactory.Options();
// First decode with inJustDecodeBounds=true to check dimensions
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
在你加载了较小的位图之后,保持对它的引用,你必须在不需要时回收,所以你需要覆盖onDetacheFromWindow函数并使用bitmap.recycle()