Android图片加载(1)

查询所有图片

最近一直在研究图片加载框架,接下来的一系列博客中,我将采取几种方式展示Android应用图片加载,大概会涉及到以下知识点:

  1. AsyncTask
  2. 多线程
  3. 线程池ExecutorServie
  4. 副线程Ui刷新的方式
  5. LruCache
  6. DiskCache
    接下来就让我们一起进入今天的环节吧,谈到图片加载,我们自然而然想到的第一个问题就是图片从哪里来,怎么拿到图片?
    想知道答案?那就接着往下看吧,Let’s Go!

Media Provider
说过怎么查看图片,有手机的人都知道,打开相册嘛,那么我们怎么拿到相册中所有图片的信息呢?这就要提到我们的MediaProvider了,那么它到底有什么用呢?

MediaProvider,顾名思义,它是媒体提供者,当手机开机或者有SD卡插拔等事件发生时,系统将会自动扫描SD卡和手机内存上的媒体文件,如audio,video,图片等,将相应的信息放到定义好的数据库表格中,而将所有查询操作分装成接口供我们调用,其中一个就是MediaProvider。

知道了它是干什么用的,那么我们就可以提取出我们要实现得到所有图片需要学习的相关知识点了:

  1. ContentResolver
  2. Cursor
    以上两个都是用于数据库(上面有提到是将详细信息存储在数据库中)
  3. HashMap
  4. List
    以上两个用于存储数据
    那么我们查询到的一张一张的图片该怎么把它抽象表示呢?自然要用到实体类,接下来我回贴出我的实体类(ImageItem)的代码,并作相关讲解:
public class ImageItem {
    private int id;
    private long lastModifyTime;
    private long size;
    private boolean isVideo;
    private long duration;
    private String path;
    private String mimeType;
    private String bucketName;
    private String displayName;
    private String title;
    private String orientation;
    private String dateTime;
    private int width;
    private int height;
    private boolean isNet;
    private String url;
    private String author;
    private int favorNumbers;
    private String description;

    public ImageItem(String url,String title,String author,String dateTime,int favornumber,String description){
        this.url = url;
        this.title = title;
        this.isVideo = false;
        this.author = author;
        this.favorNumbers =favornumber;
        this.description = description;
        this.dateTime = dateTime;
        this.isNet = true;
    }

    public ImageItem(int id, long lastModifyTime, String dateTime, long size, String path, String mimeType,
                     String bucketName, String displayName, String title, long duration, int width, int height) {
        this.id = id;
        this.lastModifyTime = lastModifyTime;
        this.size = size;
        this.path = path;
        this.mimeType = mimeType;
        this.bucketName = bucketName;
        this.displayName = displayName;
        this.title = title;
        this.duration = duration;
        this.isVideo = true;
        this.dateTime = dateTime;
        this.width = width;
        this.height = height;
    }

    public ImageItem(int id, long lastModifyTime, long size, String path, String mimeType, String bucketName, String displayName, String title, String orientation, String dateTime) {
        this.id = id;
        this.lastModifyTime = lastModifyTime;
        this.size = size;
        this.path = path;
        this.isVideo = false;
        this.mimeType = mimeType;
        this.bucketName = bucketName;
        this.displayName = displayName;
        this.title = title;
        this.dateTime = dateTime;
        this.orientation = orientation;
        this.isNet = false;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public boolean isVideo() {
        return isVideo;
    }

    public void setIsVideo(boolean isVideo) {
        this.isVideo = isVideo;
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    public boolean isNet() {
        return isNet;
    }

    public void setIsNet(boolean isNet) {
        this.isNet = isNet;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public int getFavorNumbers() {
        return favorNumbers;
    }

    public void setFavorNumbers(int favorNumbers) {
        this.favorNumbers = favorNumbers;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public long getLastModifyTime() {
        return lastModifyTime;
    }

    public void setLastModifyTime(long lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getMimeType() {
        return mimeType;
    }

    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getOrientation() {
        return orientation;
    }

    public void setOrientation(String orientation) {
        this.orientation = orientation;
    }

    public String getDateTime() {
        return dateTime;
    }

    public void setDateTime(String dateTime) {
        this.dateTime = dateTime;
    }
}

以上就是我的实体类代码,这里我参照考虑,书写了三个构造方法,分别用于网络图片,本地图片和视频的实体构造,当然这个可以根据你自己的项目需求做适量更改。

ContentResolver & Cursor
实体类构建完成后,让我们通过ContentResolver & Cursor的共同使用,从SQlite数据库中构造出我们的图片和视频对象吧,代码如下:

private ImageItem getImageItemFromCursor(Cursor cursor, boolean isVideo){
        ImageItem imageItem = null;

        if(cursor == null)
            return null;

        if(isVideo) {
            int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID));
            String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE));
            String displayName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME));
            String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE));
            String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
            String bucketName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME));
            long duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)); 
            long size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));
            int width = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.WIDTH));
            int height = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.HEIGHT));
            //The time the file was last modified Units are seconds since 1970
            long lastModifyTime = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_MODIFIED));
            String dateTime = RecyclerAdapter.getDateTimeStringFromSeconds(lastModifyTime);

            imageItem = new ImageItem(id, lastModifyTime, dateTime, size, path, mimeType,
                    bucketName, displayName, title, duration, width, height);
        }else{
            int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
            String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE));
            String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
            String displayName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
            String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.MIME_TYPE));
            long size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE));
            String bucketName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
            String orientation = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.ORIENTATION));
            long lastModifyTime = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_MODIFIED));
            String dateTime = CalculateUtils.getDateTimeStringFromSeconds(lastModifyTime);

            imageItem = new ImageItem(id,lastModifyTime,size,path,mimeType,bucketName,displayName,title,orientation,dateTime);
        }

        return imageItem;
    }

我们传入一个Cursor和一个是否是图片的标识符来构造ImageItem对象,Cursor用于查询数据序,标识符方便我们进行图片和视频的分组。

构造ImageItem已经完成,那我们就要创建Cursor,循环构造出所有的图片对象:

public synchronized HashMap<String,List<ImageItem>> getMediaHashMap(){
//HashMap用来存放所有相册,键为相册名,值为相册对应的所有图片对象列表
        HashMap<String,List<ImageItem>> retHashMap = new HashMap<String, List<ImageItem>>();

        List<ImageItem> list = null;
        boolean ret = false;

        if(mContext != null){
            //扫描photo 信息
            Cursor cursor = mContext.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null,null, null);
            //创建Cursor对象,由于ContentResolver要依赖上下文得到,所以我们函数传入了context参数
            if (cursor != null) {
                while (cursor.moveToNext()) {
//循环构造ImageItem对象,并将其存入list
                    ImageItem item = getMediaItemFromCursor(cursor, false);
                    if(item == null){
                        continue;
                    }

                    if(retHashMap.containsKey(item.getBucketName())){
                        list = retHashMap.get(item.getBucketName());
                        //同一相册就添加
                        list.add(item);
                    }else {
                    不同相册就重新new List,并把相册名作为键存入HashMap
                        list = new ArrayList<ImageItem>();
                        list.add(item);
                        retHashMap.put(item.getBucketName(), list);
                    }
                }
                //关闭Cursor
                cursor.close();
                cursor = null;
            }
            //扫描video 信息,这里与上方相同,不再赘述。

            ret = true;
        }else{
            ret = false;
        }
        return retHashMap;
    }

自此,我们本讲的问题就解决掉了,你学懂了吗?

下一讲我们会讲如何拿到图片缩略图,有兴趣的小伙伴记得关注我哦。

你可能感兴趣的:(android,图片,AsyncTask)