使用毕加索与回收者视图

时间:2016-09-20 04:05:53

标签: android out-of-memory picasso

我想在滚动回收器视图时异步加载图像。为此我用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,因此抛出空指针异常。

当我卸载应用程序并再次运行时,就会发生这种情况。在它运行良好之前。

3 个答案:

答案 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()