0

我想要什麼如何從外部存儲平滑地載入圖像?

我想爲自己創建一個自己的圖庫應用程序。 爲此,我想通過GridLayoutManager將手機上的每個圖像加載到RecyclerView中。

什麼工作

我從與路徑外部存儲每一個形象。 圖像在應用程序第一次啓動時顯示。

什麼行不通

當我在RecyclerView向下滾動immages會失真像下面的截圖。

enter image description here

我也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) 

這是我如何加載圖像

公共無效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順利?

如果不是,我的代碼有什麼問題?

+0

您可以發佈'card_view_list.xml'嗎? –

+0

當然。已經完成了! – MSeiz5

+0

我將來自ImageView country_photo的layout_width和layout_height固定爲92dp以進行測試。現在它沒有滯後或其他任何東西。 – MSeiz5

回答

1

您可能需要將縮略圖的浮點值降低爲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); 

拿到佈局PARAMS。

您可以試試CursorLoaders將圖像加載爲異步。所以UI不會掙扎。

好運

埃姆雷

+0

我將你的答案標記爲解決方案。訣竅是給imageView一個固定的大小! – MSeiz5

+1

很高興聽到它。 :) 謝謝 –

0
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);*/ 
    }