QAQ学Android真的还是要在项目中获得锻炼,脱离实际一切都是耍流氓哼唧~!
花了一下午时间搞定了项目中要实现的:获取本地图片缩略图并显示在ListView上的,并且点击要能获得该图片文件路径功能,下面先上效果图:
![](https://img-blog.csdn.net/20160524194507022?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
作为一个新手,大概碰到这种需求的思路就是:
首先,递归遍历本地所有文件,然后按文件后缀名找出所有的图片文件,更好的方式是在媒体库里查找所有的图片(系统已经帮你过滤好了所有的图片文件直接去调用就阔以了),再通过得到的文件对象file显示图像。
当然这种处理结果就是大概1~2张图片就直接OOM了。(反正我手机里图片都是至少上MB的...)。
所以呢,必须对图片进行压缩,于是我又在网上找到了一个比较好的图片压缩方法(这里没有引用转载地址了,1是因为是昨天找到的现在已经找不到网址了,2是因为很多篇博客都是相同的方法相同的注释,我也不知道到底谁才是原作...):
方法很简单,然而可以发现这个方法其实是做了这么几件事情:
1、根据传入的图片路径构造bitmap,得到原图的宽高.
2、计算图片合适的缩放比.
3、利用ThumbnailUtils来创建缩略图,然后返回这个最终缩放以后的bitmap.
尽管像方法中说的那样:使用较小的内存空间,第一次获取的bitmap实际上为null,只是为了读取宽度和高度, 第二次读取的bitmap是根据比例压缩过的图像,第三次读取的bitmap是所要的缩略图。
然而整个方法还是开辟了3个bitmap对象的内存区域,这还不考虑ThumbnailUtils.extractThumbnail()方法所耗费的时空间。
所以当我使用了这个方法实现了在ListView中遍历本地图片的时候,上下滑起来是灰常卡滴(这里就不贴gif图了有兴趣想知道的朋友可以自己尝试一下)
Finaly,在踏破铁鞋无觅处之后,终于找到了最终解决方法,也是一开始忽略的方法:
原来一直不知道的Thumbnails类,才是解决问题的关键。
在Android系统中也有对应的thumbnails文件,下面是百度百科对它的描述:
![](https://img-blog.csdn.net/20160524202241837?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
然后在MediaStore媒体库类中,也是有Thumbnails这么一个内部类的:
-
-
-
-
-
- public static class Thumbnails implements BaseColumns {
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
- return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind,
- String[] projection) {
- return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind,
- String[] projection) {
- return cr.query(EXTERNAL_CONTENT_URI, projection,
- IMAGE_ID + " = " + origId + " AND " + KIND + " = " +
- kind, null, null);
- }
-
-
-
-
-
-
-
-
-
- public static void cancelThumbnailRequest(ContentResolver cr, long origId) {
- InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI,
- InternalThumbnails.DEFAULT_GROUP_ID);
- }
-
-
-
-
-
-
-
-
-
-
-
-
- public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind,
- BitmapFactory.Options options) {
- return InternalThumbnails.getThumbnail(cr, origId,
- InternalThumbnails.DEFAULT_GROUP_ID, kind, options,
- EXTERNAL_CONTENT_URI, false);
- }
-
-
-
-
-
-
-
-
-
-
- public static void cancelThumbnailRequest(ContentResolver cr, long origId, long groupId) {
- InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI, groupId);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId,
- int kind, BitmapFactory.Options options) {
- return InternalThumbnails.getThumbnail(cr, origId, groupId, kind, options,
- EXTERNAL_CONTENT_URI, false);
- }
-
-
-
-
-
-
-
-
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/images/thumbnails");
- }
-
-
-
-
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
-
-
-
-
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
-
-
-
- public static final String DEFAULT_SORT_ORDER = "image_id ASC";
-
-
-
-
-
- public static final String DATA = "_data";
-
-
-
-
-
- public static final String IMAGE_ID = "image_id";
-
-
-
-
-
- public static final String KIND = "kind";
-
- public static final int MINI_KIND = 1;
- public static final int FULL_SCREEN_KIND = 2;
- public static final int MICRO_KIND = 3;
-
-
-
-
- public static final String THUMB_DATA = "thumb_data";
-
-
-
-
-
- public static final String WIDTH = "width";
-
-
-
-
-
- public static final String HEIGHT = "height";
- }
- }
我们可以从中找到几个可用于Cursor查找的重要参数:
/**
* The data stream for the thumbnail
* <P>Type: DATA STREAM</P>
*/
public static final String DATA = "_data";
/**
* The original image for the thumbnal
* <P>Type: INTEGER (ID from Images table)</P>
*/
public static final String IMAGE_ID = "image_id";
/**
* The content:// style URI for the "primary" external storage
* volume.
*/
public static final Uri EXTERNAL_CONTENT_URI =
getContentUri("external");
有了这三个参数,我们就可以很轻松从本地媒体库中获得图片缩略图的ID和路径。
-
- Cursor cursor = cr.query(
- Thumbnails.EXTERNAL_CONTENT_URI,
- new String[]{
- Thumbnails.IMAGE_ID,
- Thumbnails.DATA
- },
- null,
- null,
- null);
这里的缩略图ID有什么用呢?我们从它的注释中可以很明显地得到:
/**
* The original image for the thumbnal
* <P>Type: INTEGER (ID from Images table)</P>
ID from Images table!!!这个ID是跟多媒体库中的images表的ID相对应的,由此,我们可以通过这个id来设置cursor的查找条件,从而找出images表中对应的真正的图片文件的路径!
从而完美地实现了文章开头的功能需求。
下面是完整的代码:
获得一个HashMap参数的ArrayList,HashMap项的键"thumbnail_path"对应真实图片路径值,键"image_id_path"对应缩略图路径值,有了这两个路径,想干嘛干嘛了2333
-
-
-
-
-
- public static ArrayList<HashMap<String,String>> getAllPictures(Context context) {
- ArrayList<HashMap<String,String>> picturemaps = new ArrayList<>();
- HashMap<String,String> picturemap;
- ContentResolver cr = context.getContentResolver();
-
- Cursor cursor = cr.query(
- Thumbnails.EXTERNAL_CONTENT_URI,
- new String[]{
- Thumbnails.IMAGE_ID,
- Thumbnails.DATA
- },
- null,
- null,
- null);
- if (cursor.moveToFirst()) {
- do {
- picturemap = new HashMap<>();
- picturemap.put("image_id_path",cursor.getInt(0)+"");
- picturemap.put("thumbnail_path",cursor.getString(1));
- picturemaps.add(picturemap);
- } while (cursor.moveToNext());
- cursor.close();
- }
-
- for (int i = 0;i<picturemaps.size();i++) {
- picturemap = picturemaps.get(i);
- String media_id = picturemap.get("image_id_path");
- cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- new String[]{
- MediaStore.Images.Media.DATA
- },
- MediaStore.Audio.Media._ID+"="+media_id,
- null,
- null
- );
- if (cursor.moveToFirst()) {
- do {
- picturemap.put("image_id",cursor.getString(0));
- picturemaps.set(i,picturemap);
- } while (cursor.moveToNext());
- cursor.close();
- }
- }
- return picturemaps;
- }