Как загрузить изображения из внешнего хранилища, гладкие с Glide?

Что я хочу

Я хочу создать собственное приложение для галереи. Для этого я хочу загрузить каждое изображение на телефоне в RecyclerView от GridLayoutManager.

Что работает

Я получил каждое изображение из внешнего хранилища с путем. Изображения отображаются при первом запуске приложения.

Что не работает

Когда я прокручиваю вниз в моем RecyclerView, изображения будут искажены, как на скриншоте ниже.

Я также получил эту ошибку 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)

Вот так я загружаю изображения

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);

}

Это адаптер

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>

Мои вопросы

Есть ли лучший способ плавно загружать изображения в GridView?

Если нет, что не так с моим кодом?

2 ответа

Решение

Возможно, вам понадобится уменьшить значение с плавающей точкой на 0.2f или 0.1f.

Также вы можете попробовать MediaStore.Images.Thumbnails или другой способ получить эскиз с вашей проекцией. Не гарантируется, что на каждом изображении есть миниатюра. Вы должны также контролировать это.

В вашем запросе на скольжение вы можете удалить .asBitmap() если вы не против использовать обратный вызов для зависания с растровым изображением.

Вы можете надуть как

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

вместо

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

чтобы получить параметры макета.

Вы можете попробовать CursorLoaders для загрузки изображений в асинхронном режиме. Таким образом, пользовательский интерфейс не будет бороться.

Удачи

Эмре

 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);*/
    }
Другие вопросы по тегам