MSeiz5
MSeiz5

Reputation: 222

How to load images from external storage smooth with glide?

What I want

I want to greate an own gallery application for myself. For that I want to load every image on the phone into a RecyclerView by GridLayoutManager.

What does work

I got every image from external storage with path. Images are displayed by the first time the app is started.

What does not work

When I scroll down in my RecyclerView the immages will be distorted like in the screenshot below.

enter image description here

I also got this error by logcat:

Process: com.spicysoftware.gallery, PID: 12209
                                                                           java.lang.RuntimeException: Canvas: trying to draw too large(115650308bytes) bitmap.
                                                                               at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java)
                                                                               at android.graphics.Canvas.drawBitmap(Canvas.java)
                                                                               at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java)
                                                                               at android.widget.ImageView.onDraw(ImageView.java)
                                                                               at android.view.View.draw(View.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.View.draw(View.java)
                                                                               at android.view.ViewGroup.drawChild(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchDraw(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.View.draw(View.java)
                                                                               at android.view.ViewGroup.drawChild(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchDraw(ViewGroup.java)
                                                                               at android.view.View.draw(View.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.View.draw(View.java)
                                                                               at android.view.ViewGroup.drawChild(ViewGroup.java)
                                                                               at android.support.v7.widget.RecyclerView.drawChild(RecyclerView.java:4477)
                                                                               at android.view.ViewGroup.dispatchDraw(ViewGroup.java)
                                                                               at android.view.View.draw(View.java)
                                                                               at android.support.v7.widget.RecyclerView.draw(RecyclerView.java:3869)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java)
                                                                               at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java)
                                                                               at android.view.View.updateDisplayListIfDirty(View.java)
                                                                               at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java)
                                                                               at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java)
                                                                               at android.view.ThreadedRenderer.draw(ThreadedRenderer.java)
                                                                               at android.view.ViewRootImpl.draw(ViewRootImpl.java)
                                                                               at android.view.ViewRootImpl.performDraw(ViewRootImpl.java)
                                                                               at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java)
                                                                               at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java)
                                                                               at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java)
                                                                               at android.view.Choreographer$CallbackRecord.run(Choreographer.java)
                                                                               at android.view.Choreographer.doCallbacks(Choreographer.java)
                                                                               at android.view.Choreographer.doFrame(Choreographer.java)
                                                                               at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java)
                                                                               at android.os.Handler.handleCallback(Handler.java)
                                                                               at android.os.Handler.dispatchMessage(Handler.java)
                                                                               at android.os.Looper.loop(Looper.java)
                                                                               at android.app.ActivityThread.main(ActivityThread.java)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)

This is how I load the images

public void loadAllImages(){

String[] mProjection = {MediaStore.Images.Media.DATE_TAKEN,MediaStore.Images.Media.DATA};
Cursor cursorImagesExternal = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,mProjection,null,null,MediaStore.Images.Media.DATE_ADDED);
List<ItemObject> allItems = new ArrayList<ItemObject>();
int countImages = 0;

while(cursorImagesExternal.moveToNext()) {
    long date = cursorImagesExternal.getLong(0);
    String fileLoc = cursorImagesExternal.getString(1);
    allItems.add(new ItemObject(fileLoc));
    countImages ++;
}

Log.v("Image Count: ", ""+countImages);

List<ItemObject> rowListItem = allItems;
lLayout = new GridLayoutManager(MainActivity.this, 4);

RecyclerView rView = (RecyclerView)findViewById(R.id.recycler_view);
rView.setHasFixedSize(true);
rView.setLayoutManager(lLayout);

RecyclerViewAdapter rcAdapter = new RecyclerViewAdapter(MainActivity.this, rowListItem);
rView.setAdapter(rcAdapter);

}

This is the adapter

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> {

    private List<ItemObject> itemList;
    private Context context;

    public RecyclerViewAdapter(Context context, List<ItemObject> itemList) {
        this.itemList = itemList;
        this.context = context;
    }

    @Override
    public RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {

        View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_list, null);
        RecyclerViewHolders rcv = new RecyclerViewHolders(layoutView);
        return rcv;
    }

    @Override
    public void onBindViewHolder(final RecyclerViewHolders holder, int position) {
        //holder.countryName.setText(itemList.get(position).getName());

        Glide.with(context).asBitmap()
                .load(itemList.get(position).getName())
                .thumbnail(0.5f)
                .into(holder.countryPhoto);


    }

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

card_view_list.xml

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/card_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="4"
    card_view:cardUseCompatPadding="true"
    android:layout_marginBottom="16dp">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/country_photo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@string/action_settings"
            android:src="@drawable/ic_remove_red_eye_black_24dp"
            android:scaleType="centerCrop" />

    </RelativeLayout>

</android.support.v7.widget.CardView>

My Questions

Is there a better way to load images to a GridView smoothly?

If not, what is wrong with my code?

Upvotes: 1

Views: 2482

Answers (2)

Emre Akt&#252;rk
Emre Akt&#252;rk

Reputation: 3346

You may need to lower thumbnail float something like 0.2f or 0.1f.

Also you can give it a try MediaStore.Images.Thumbnails or another way to get thumbnail with your projection. Its not guaranteed that every image has thumbnail. You need to control it also.

In your glide request, you can remove .asBitmap() if you dont mind to use callback to hang with bitmap.

You can inflate like

 View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_list, parent, false); 

instead

 View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_list, null);

to get layout params.

You may give it a try to CursorLoaders to load images as async. So UI wont be struggled.

Good luck

Emre

Upvotes: 1

Jaspreet Kaur
Jaspreet Kaur

Reputation: 1720

 int defaultImagePath = R.drawable.default_thumb;
int errorImagePath = R.drawable.damaged_image;
 holder.countryPhoto.setImageResource(defaultImagePath);

String uri = itemList.get(position).getName();
loadImageWithGlide(mContext, holder.countryPhoto, uri, defaultImagePath,
                        errorImagePath);



public static void loadImageWithGlide(final Context context, ImageView theImageViewToLoadImage,
                                          String theLoadImagePath, int theDefaultImagePath, int tehErrorImagePath) {
        if (context == null) return;

        //placeHolderUrl=R.drawable.ic_user;
        //errorImageUrl=R.drawable.ic_error;
        Glide.with(context) //passing context
                .load(theLoadImagePath) //passing your url to load image.
                .placeholder(theDefaultImagePath) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
                .error(tehErrorImagePath)//in case of any glide exception or not able to download then this image will be appear . if you won't mention this error() then nothing to worry placeHolder image would be remain as it is.
                .diskCacheStrategy(DiskCacheStrategy.ALL) //using to load into cache then second time it will load fast.
                //.animate(R.anim.fade_in) // when image (url) will be loaded by glide then this face in animation help to replace url image in the place of placeHolder (default) image.
                //.fitCenter()//this method help to fit image into center of your ImageView
                .into(theImageViewToLoadImage); //pass imageView reference to appear the image.

        /*  Normal way to Load Image with Glide.
                Glide.with(theContext)
                .load(theImagePath)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(theImageView);*/
    }

Upvotes: 0

Related Questions