javaandroidandroid-glide

Using Glide Library with a Fragment adapter


I have an adapter class that is being used to populate the recyclerview item with cardviews. This RecyclerView is located under a fragment. Inside this adapter, I am trying to bind an image to a imageview which is under the cardview layout. I am trying to achieve that under the following method which is in the adapter class:

public void onBindViewHolder(@NonNull ProductViewHolder holder, int position) {
    Product product = myProducts.get(position);
    holder.productTitle.setText(product.getProductName());
    holder.productDesc.setText(product.getDescription());
    Uri uri = Uri.parse(product.getImageUri());
    Glide.with(/*WHAT SHOULD I PASS HERE??*/).load(new File(uri.getPath())).into(holder.productImage);
}

Each product instance has a field which contains path to an image and I want to take that path, find corresponding image and draw it in the cardview item. But I have no idea what should I pass to Glide.with() as an argument. Thanks in advance and please point out anything seems wrong. I am very novice in android programming.

Edit: Following is the holder class.

class ProductViewHolder extends RecyclerView.ViewHolder {

    private ImageView productImage;
    private TextView productTitle;
    private TextView productDesc;

    public ProductViewHolder(View itemView) {
        super(itemView);
        productImage = itemView.findViewById(R.id.product_image);
        productTitle = itemView.findViewById(R.id.product_title);
        productDesc = itemView.findViewById(R.id.product_desc);
    }

}

And I have tried this

Glide.with(holder.itemView).load(new File(uri.getPath())).into(holder.productImage);

But it gave an error like this:

class com.bumptech.glide.load.engine.GlideException: Failed to load resource
There were 3 causes:
java.io.IOException(File unsuitable for memory mapping)
java.io.FileNotFoundException(/document/msf:24: open failed: ENOENT (No such file or directory))
java.io.FileNotFoundException(open failed: ENOENT (No such file or directory))

This is my adapter class:

 public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductViewHolder> {

    private final LayoutInflater myInflater;
    private List<Product> myProducts = new ArrayList<>();
    private Context context;

    public ProductAdapter(Context context) {
        this.context = context;
        myInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = myInflater.inflate(R.layout.card_view_product, parent, false);
        return new ProductViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull ProductViewHolder holder, int position) {
        Product product = myProducts.get(position);
        holder.productTitle.setText(product.getProductName());
        holder.productDesc.setText(product.getDescription());
        Uri uri = Uri.parse(product.getImageUri());
        Glide.with(context).load(new File(uri.getPath())).into(holder.productImage);
    }

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

    public void setProducts(List<Product> products) {
        myProducts = products;
        notifyDataSetChanged();
    }

    class ProductViewHolder extends RecyclerView.ViewHolder {

        private ImageView productImage;
        private TextView productTitle;
        private TextView productDesc;

        public ProductViewHolder(View itemView) {
            super(itemView);
            productImage = itemView.findViewById(R.id.product_image);
            productTitle = itemView.findViewById(R.id.product_title);
            productDesc = itemView.findViewById(R.id.product_desc);
        }

    }
}

And the error

    W/Glide: Load failed for /document/msf:25 with size [384x384]
    class com.bumptech.glide.load.engine.GlideException: Failed to load resource
    There were 3 causes:
    java.io.IOException(File unsuitable for memory mapping)
    java.io.FileNotFoundException(/document/msf:25: open failed: ENOENT (No such file or directory))
    java.io.FileNotFoundException(open failed: ENOENT (No such file or directory))
     call GlideException#logRootCauses(String) for more detail
      Cause (1 of 3): class com.bumptech.glide.load.engine.GlideException: Fetching data failed, class java.nio.ByteBuffer, LOCAL
    There was 1 cause:
    java.io.IOException(File unsuitable for memory mapping)
     call GlideException#logRootCauses(String) for more detail
        Cause (1 of 1): class java.io.IOException: File unsuitable for memory mapping
      Cause (2 of 3): class com.bumptech.glide.load.engine.GlideException: Fetching data failed, class java.io.InputStream, LOCAL
    There was 1 cause:
    java.io.FileNotFoundException(/document/msf:25: open failed: ENOENT (No such file or directory))
     call GlideException#logRootCauses(String) for more detail
        Cause (1 of 1): class java.io.FileNotFoundException: /document/msf:25: open failed: ENOENT (No such file or directory)
      Cause (3 of 3): class com.bumptech.glide.load.engine.GlideException: Fetching data failed, class android.os.ParcelFileDescriptor, LOCAL
    There was 1 cause:
    java.io.FileNotFoundException(open failed: ENOENT (No such file or directory))
     call GlideException#logRootCauses(String) for more detail
        Cause (1 of 1): class java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
I/Glide: Root cause (1 of 3)
    java.io.IOException: File unsuitable for memory mapping
        at com.bumptech.glide.util.ByteBufferUtil.fromFile(ByteBufferUtil.java:38)
        at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:61)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
        at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
        at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393)
I/Glide: Root cause (2 of 3)
    java.io.FileNotFoundException: /document/msf:25: open failed: ENOENT (No such file or directory)
        at libcore.io.IoBridge.open(IoBridge.java:496)
        at java.io.FileInputStream.<init>(FileInputStream.java:159)
        at com.bumptech.glide.load.model.FileLoader$StreamFactory$1.open(FileLoader.java:142)
        at com.bumptech.glide.load.model.FileLoader$StreamFactory$1.open(FileLoader.java:139)
        at com.bumptech.glide.load.model.FileLoader$FileFetcher.loadData(FileLoader.java:71)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:408)
        at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:160)
        at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:83)
        at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:66)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
        at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
        at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393)
     Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
        at libcore.io.IoBridge.open(IoBridge.java:482)
        at java.io.FileInputStream.<init>(FileInputStream.java:159) 
        at com.bumptech.glide.load.model.FileLoader$StreamFactory$1.open(FileLoader.java:142) 
        at com.bumptech.glide.load.model.FileLoader$StreamFactory$1.open(FileLoader.java:139) 
        at com.bumptech.glide.load.model.FileLoader$FileFetcher.loadData(FileLoader.java:71) 
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70) 
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63) 
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310) 
        at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:408) 
        at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:160) 
        at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:83) 
        at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:66) 
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70) 
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63) 
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310) 
        at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279) 
        at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:919) 
        at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393) 
I/Glide: Root cause (3 of 3)
    java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
        at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:315)
        at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:220)
        at com.bumptech.glide.load.model.FileLoader$FileDescriptorFactory$1.open(FileLoader.java:166)
        at com.bumptech.glide.load.model.FileLoader$FileDescriptorFactory$1.open(FileLoader.java:163)
        at com.bumptech.glide.load.model.FileLoader$FileFetcher.loadData(FileLoader.java:71)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:408)
        at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:160)
        at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:83)
        at com.bumptech.glide.load.model.FileLoader$FileFetcher.loadData(FileLoader.java:76)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:408)
        at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:160)
        at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:83)
        at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:66)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
        at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
        at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393)

I debug the code to see does the path of an image returns successfully and it does. But it is not showing up in the list item. I think there is nothing wrong in the part where addition process happens.


Solution

  • you need to pass the context of your activity/fragment which contains the image view in the with().

    you can achieve this by passing the context of your activity in your adapter constructor. for example, your Adapter constructor might look like that:

    myAdapter(Context context, List<Object> dataset) {
                this.context = context;
                ...
                ...
                   }
    

    and when you create an instance from the adapter you can pass the context like this:

    myAdapter adapter = new MyAdapter(this,...);
    

    then you can use the context for Glide like this:

    Glide.with(context)
    

    I hope this helps, if you need more clarifications, let me know in the comments!