Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error, cannot access an invalid/free'd bitmap here! while using a Model Class containing Bitmap

In my app I'm using model class containing a Bitmap for displaying an image on recyclerView

public class ImageModelClass {

Bitmap image;

public void setImage(Bitmap image) {
    this.image = image;
}

public Bitmap getImage() {
    return image;
}

Problem is when i am using Bitmap directly from my model class then this error is throwing Error, cannot access an invalid/free'd bitmap here!

and when i replace the Bitmap Class to a String in my model class and using encoded bitmap i converted bitmap Image into a String then this error isn't coming .

But encoding a Bitmap is taking lot of time load images.

public class ImageCollection extends AppCompatActivity {
public static final String IMAGE_SHARED_PREFS = "com.example.animproject_IMAGE_SHARED_PREFS";
public static final String IMAGE_DATA_KEY = "com.example.animproject_IMAGE_DATA_KEY";

private static final int REQUEST_CODE = 1;
RecyclerView recyclerView;
ImageCollectionAdapter adapter;
List<ImageModelClass> imageList;
FloatingActionButton fab;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_image_collection);

    loadAlbumData();
    recyclerView = findViewById(R.id.imageCollectionRecyclerView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

    adapter = new ImageCollectionAdapter(this,imageList);
    StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, GridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(staggeredGridLayoutManager);
    recyclerView.setAdapter(adapter);

    fab = findViewById(R.id.fabButton);
    fab.setOnClickListener(new View.OnClickListener() {
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onClick(View view) {
            Intent gallery = new Intent(Intent.ACTION_PICK);
            gallery.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            gallery.setType("image/*");

            startActivityForResult(gallery, REQUEST_CODE);
        }
    });

}


@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
        assert data != null;
        ClipData clipData = data.getClipData();

        if (clipData != null) {
            for (int i = 0; i < clipData.getItemCount(); i++) {

                Uri imageUri = clipData.getItemAt(i).getUri();
                InputStream inputStream;

                try {
                    inputStream = getContentResolver().openInputStream(imageUri);
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    ImageModelClass imageModelClass = new ImageModelClass();
                    imageModelClass.setImage(bitmap);

                    imageList.add(imageModelClass);
                    adapter.notifyDataSetChanged();
                    saveGalleryData();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

            }
        } else {
            Uri imageUri = data.getData();
            InputStream inputStream = null;
            try {
                assert imageUri != null;
                inputStream = getContentResolver().openInputStream(imageUri);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            ImageModelClass imageModelClass = new ImageModelClass();
            imageModelClass.setImage(bitmap);

            imageList.add(imageModelClass);
            adapter.notifyDataSetChanged();
            saveGalleryData();
        }
    }
}

private void saveGalleryData() {
    SharedPreferences preferences = getSharedPreferences(IMAGE_SHARED_PREFS, MODE_PRIVATE);
    SharedPreferences.Editor editor = preferences.edit();
    Gson gson = new Gson();
    String json = gson.toJson(imageList);
    editor.putString(IMAGE_DATA_KEY, json);
    editor.apply();
}

private void loadAlbumData() {
    SharedPreferences preferences = getSharedPreferences(IMAGE_SHARED_PREFS, MODE_PRIVATE);
    Gson gson = new Gson();
    Type type = new TypeToken<ArrayList<ImageModelClass>>() {
    }.getType();
    String data = preferences.getString(IMAGE_DATA_KEY, null);
    imageList = gson.fromJson(data, type);

    if (imageList == null) {
        imageList = new ArrayList<>();
    }
}

}

Adapter

public class ImageCollectionAdapter extends RecyclerView.Adapter<ImageCollectionAdapter.MyViewHolder> {

List<ImageModelClass> list;
Context context;


public ImageCollectionAdapter(Context context,List<ImageModelClass> list) {
    this.list = list;
    this.context = context ;
}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new MyViewHolder(LayoutInflater.from(parent.getContext())
            .inflate(R.layout.image_collection_lists, parent, false));
}


@Override
public void onBindViewHolder(@NonNull  
MyViewHolder holder, int position) {
   ImageModelClass currentImage = 
  list.get(position);    

 Glide
.With(context.getApplicationContext)
.load(currentImages.getImages) 
 /* getting bitmap images from model 
  * class 
  */
.into(holder.imageView); 
      


} 

@Override
public int getItemCount() {
    return list.size();
}

public class MyViewHolder extends RecyclerView.ViewHolder {
    RoundedImageView imageView;

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        imageView = itemView.findViewById(R.id.galleryPicture);
    }
}
}

please help it will be appreciatable :)

like image 872
Kaunain Avatar asked Oct 24 '25 13:10

Kaunain


1 Answers

I was facing the same issue when I was trying to get the bitmap from the textView. The textView was in the RecyclerView inside a bottom sheet. When I clicked on textView I was getting the bitmap and dismissing the bottom sheet.

I got the bitmap from the drawing cache of the textView. I checked it using the debugger the bitmap was retrieved correctly. But when I passed it to callback (from recyclerView's adapter to activity), the bitmap in the callback is not shown in the debugger and I got the error 'cannot access an invalid/free'd bitmap here!'.

As of my understanding, When textView is not shown/rendered on the screen (In my case when I dismissed the bottom sheet) the cached bitmap becomes unavailable. Gotta read the relevant docs to know the exact cause of the problem.

What I did to solve this issue is to create a copy of the bitmap and pass it to the callback and It worked!

You can copy the bitmap like this:

Bitmap copyBitmap = bitmap.copy(bitmap.getConfig(), false);

The full code of retrieving the bitmap and creating new one:

       holder.textView.setDrawingCacheEnabled(true);
       holder.textView.buildDrawingCache();
       Bitmap bitmap = holder.textView.getDrawingCache();
       Bitmap copyBitmap = bitmap.copy(bitmap.getConfig(), false);
       holder.textView.setDrawingCacheEnabled(false);
       callback.onWidgetSelected(copyBitmap);

I hope you'll find it helpful. I'll make sure to study the docs as well and will update the answer when I find the cause of this problem.

like image 61
Haxxan Parhar Developer Avatar answered Oct 27 '25 03:10

Haxxan Parhar Developer