如何从外部存储平滑地加载图像?
How to load images from external storage smooth with glide?
我想要的
我想为自己开发一个自己的画廊应用程序。
为此,我想通过 GridLayoutManager 将 phone 上的每个图像加载到 RecyclerView 中。
什么有效
我从外部存储中获取了每张带有路径的图像。
应用程序第一次启动时显示图像。
什么不起作用
当我在我的 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 中?
如果不是,我的代码有什么问题?
您可能需要降低缩略图浮动,例如 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 以异步方式加载图像。所以UI不会纠结
祝你好运
埃姆雷
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);*/
}
我想要的
我想为自己开发一个自己的画廊应用程序。 为此,我想通过 GridLayoutManager 将 phone 上的每个图像加载到 RecyclerView 中。
什么有效
我从外部存储中获取了每张带有路径的图像。 应用程序第一次启动时显示图像。
什么不起作用
当我在我的 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 中?
如果不是,我的代码有什么问题?
您可能需要降低缩略图浮动,例如 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 以异步方式加载图像。所以UI不会纠结
祝你好运
埃姆雷
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);*/
}