在服务器上存储多大尺寸的图像以与Android应用程序配合使用
我有一个Android应用程序,允许用户上传个人资料图片。它们在服务器上存储为300px 300px 在这个应用程序中,我使用40dp X 40dp或有时使用100dp X 100dp。40dp的图像位于在服务器上存储多大尺寸的图像以与Android应用程序配合使用,android,listview,bitmap,imageview,Android,Listview,Bitmap,Imageview,我有一个Android应用程序,允许用户上传个人资料图片。它们在服务器上存储为300px 300px 在这个应用程序中,我使用40dp X 40dp或有时使用100dp X 100dp。40dp的图像位于列表视图中。实际上,我使用非常流行的第三方LazyList将图像存储在缓存中(使用ImageLoader类) 我只需在我的适配器中显示图像,如下所示: imageLoader.DisplayImage(profileUrl, holder.iv1); 我获取web URL并将其直接显示在Ima
列表视图中。实际上,我使用非常流行的第三方LazyList
将图像存储在缓存中(使用ImageLoader
类)
我只需在我的适配器中显示图像,如下所示:
imageLoader.DisplayImage(profileUrl, holder.iv1);
我获取web URL并将其直接显示在ImageView
40dp x 40dp中
有时我会注意到图像退化。如果图像部分加载,则图像已损坏
一种理论是,从服务器上的一个大图像开始,尝试将其存储在实际应用程序中的一个小区域中,然后在列表视图中多次这样做,这会导致一些加载问题
问题:当服务器中的图像比需要显示的图像大得多时,处理这种情况的最佳方法是什么?我假设我可能需要使用BitMapFactory
或类似的类来构建新映像。但我不确定。我觉得我错过了一步
下面是一个列表视图
中的图像已损坏的示例,请注意,并非所有图像都已损坏。(是的,那是来自发展部的托比亚斯。)
跟进:当图像来自服务器而不是资源文件夹时,我们如何考虑xxhdpi
、xhdpi
等的文件大小
我建议在用于请求图像的URL中添加一个参数(例如,&size=small
),并让服务器保留每个图像的多个大小。这样做的一些好处是:
减少应用程序中的数据使用量
更好的图像质量(无需对图像重新采样)
更好的性能(大型位图需要更长的加载时间)
缺点是:
更复杂(用于确定要请求的大小的逻辑)
服务器上的更多存储要求
我认为利大于弊,最终你会获得更好的用户体验
在后续工作中,您甚至可以为每个密度(例如,&density=mdpi
)设置参数,以提供适当的大小(并且您可以只打开getResources().getDisplayMetrics().densityDpi
来获取参数值)
例如:
int densityDpi = getResources().getDisplayMetrics().densityDpi;
if (densityDpi <= DisplayMetrics.DENSITY_MEDIUM) {
return "mdpi";
} else if (densityDpi <= DisplayMetrics.DENSITY_HIGH) {
return "hdpi";
} else if (densityDpi <= DisplayMetrics.DENSITY_XHIGH) {
return "xhdpi";
} else if (densityDpi <= DisplayMetrics.DENSITY_XXHIGH) {
return "xxhdpi";
} else {
return "xxxhdpi";
}
int densityDpi=getResources().getDisplayMetrics().densityDpi;
如果(densityDpi您正在使用的库看起来几乎不再维护(上次更新至少有一年了)。有几个更新的、可能更好的库可以解决相同的问题。我最喜欢的是。它使用非常简单,很好地解决了ListView中的图像加载问题
要更直接地回答您的一些问题:
当你有很多钱的时候,处理这种情况的最好方法是什么
服务器中的图像是否比需要显示的图像大
你需要对位图进行二次采样,直到达到目标大小。谷歌对所有这些都有很好的描述
首先,您必须对位图进行解码,设置inJustDecodeBounds
布尔值以获得位图大小
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
然后,您可以根据目标高度和宽度计算样本大小
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
然后,您可以使用计算出的样本大小加载向下采样的位图
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
当图像来自服务器而不是资源文件夹时,我们如何考虑xxhdpi、xhdpi等的文件大小
可以使用以下代码段计算要缩小位图的目标像素大小:
float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, "10", context.getResources().getDisplayMetrics());
太长,读不下去了
使用它,它将解决您所有的问题。该库非常完美!仅此250分就值了!好吧,它几乎完美了,我希望有一种简单的方法来清除缓存。我确实看到了,但我不确定如何访问代码,因为它是一个jar文件。我确信我能找到它,但最终,我没有实现我需要这个函数,正如我所想的那样。不管怎样,听起来毕加索的人很快就会实现它。你只需要在com.squareup.Picasso包中创建毕加索工具类。这样你就可以访问包私有缓存。@jamesmcracken我正在使用毕加索resize with centrecrop,但我的recyclerview是挂起我的意思是图片已经被缓存了,但是recyclerview挂起了。你能告诉我可能的问题是什么,或者我应该用什么来代替调整大小吗??