Android 根据相册预览内存中的图片和视屏

前言: 在开发中有个需求需要访问本地图片和视屏进行上传,所以尝试了以下访问本地的图片和视屏并利用gridView展示出来。

正文

一、先创建一个异步任务用于查询数据库中图片、相册、视屏等数据,代码如下:

package com.example.test1.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.example.test1.R;
import com.example.test1.bean.PhotoUpImageBucket;
import com.example.test1.bean.PhotoUpImageItem;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.Albums;
import android.provider.MediaStore.Images.Media;
import android.provider.MediaStore.Images.Thumbnails;
import android.util.Log;

public class PhotoUpAlbumHelper extends AsyncTask<Object, Object, Object>{

    final String TAG = "PhotoUpAlbumHelper";
    Context context;
    ContentResolver cr;
    // 缩略图列表
    HashMap<String, String> thumbnailList = new HashMap<String, String>();
    // 专辑列表
    List<HashMap<String, String>> albumList = new ArrayList<HashMap<String, String>>();
    HashMap<String, PhotoUpImageBucket> bucketList = new HashMap<String, PhotoUpImageBucket>();
    private GetAlbumList getAlbumList;
    //视屏列表
    List<HashMap<String, String>> videoList = new ArrayList<HashMap<String,String>>();
    
    private PhotoUpAlbumHelper() {}
    public static PhotoUpAlbumHelper getHelper() {
        PhotoUpAlbumHelper instance = new PhotoUpAlbumHelper();
        return instance;
    }

    /**
     * 初始化
     * @param context
     */
    public void init(Context context) {
        if (this.context == null) {
            this.context = context;
            cr = context.getContentResolver();
        }
    }

    /**
     * 得到缩略图
     */
    private void getThumbnail() {
        String[] projection = { Thumbnails._ID, Thumbnails.IMAGE_ID,
                Thumbnails.DATA};
        Cursor cursor1 = Thumbnails.queryMiniThumbnails(cr, Thumbnails.EXTERNAL_CONTENT_URI,
                Thumbnails.MINI_KIND, projection);
        getThumbnailColumnData(cursor1);
        cursor1.close();
    }

    /**
     * 从数据库中得到缩略图
     * @param cur
     */
    private void getThumbnailColumnData(Cursor cur) {
        if (cur.moveToFirst()) {
            int image_id;
            String image_path;
            int image_idColumn = cur.getColumnIndex(Thumbnails.IMAGE_ID);
            int dataColumn = cur.getColumnIndex(Thumbnails.DATA);
            do {
                image_id = cur.getInt(image_idColumn);
                image_path = cur.getString(dataColumn);
                thumbnailList.put("" + image_id, image_path);
            } while (cur.moveToNext());
        }
    }

    /**
     * 得到原图-n
     */
    void getAlbum() {
        String[] projection = { Albums._ID, Albums.ALBUM, Albums.ALBUM_ART,
                Albums.ALBUM_KEY, Albums.ARTIST, Albums.NUMBER_OF_SONGS };
        Cursor cursor1 = cr.query(Albums.EXTERNAL_CONTENT_URI, projection, null,
                null, Albums.ALBUM_ID+" desc");
        getAlbumColumnData(cursor1);
        cursor1.close();
    }

    /**
     * 从本地数据库中得到原图
     * @param cur
     */
    private void getAlbumColumnData(Cursor cur) {
        if (cur.moveToFirst()) {
            int _id;
            String album;
            String albumArt;
            String albumKey;
            String artist;
            int numOfSongs;
            int _idColumn = cur.getColumnIndex(Albums._ID);
            int albumColumn = cur.getColumnIndex(Albums.ALBUM);
            int albumArtColumn = cur.getColumnIndex(Albums.ALBUM_ART);
            int albumKeyColumn = cur.getColumnIndex(Albums.ALBUM_KEY);
            int artistColumn = cur.getColumnIndex(Albums.ARTIST);
            int numOfSongsColumn = cur.getColumnIndex(Albums.NUMBER_OF_SONGS);
            do {
                _id = cur.getInt(_idColumn);
                album = cur.getString(albumColumn);
                albumArt = cur.getString(albumArtColumn);
                albumKey = cur.getString(albumKeyColumn);
                artist = cur.getString(artistColumn);
                numOfSongs = cur.getInt(numOfSongsColumn);
                HashMap<String, String> hash = new HashMap<String, String>();
                hash.put("_id", _id + "");
                hash.put("album", album);
                hash.put("albumArt", albumArt);
                hash.put("albumKey", albumKey);
                hash.put("artist", artist);
                hash.put("numOfSongs", numOfSongs + "");
                albumList.add(hash);
            } while (cur.moveToNext());
        }
    }

    /**
     * 是否创建了图片集
     */
    boolean hasBuildImagesBucketList = false;
    /**
     * 得到图片集
     */
    void buildImagesBucketList() {
        // 构造缩略图索引
        getThumbnail();
        // 构造相册索引
        String columns[] = new String[] { Media._ID, Media.BUCKET_ID,
                Media.PICASA_ID, Media.DATA, Media.DISPLAY_NAME, Media.TITLE,
                Media.SIZE, Media.BUCKET_DISPLAY_NAME };
        // 得到一个游标
        Cursor cur = cr.query(Media.EXTERNAL_CONTENT_URI, columns, null, null,
                Media.DATE_MODIFIED+" desc");
        if (cur.moveToFirst()) {
            // 获取指定列的索引
            int photoIDIndex = cur.getColumnIndexOrThrow(Media._ID);
            int photoPathIndex = cur.getColumnIndexOrThrow(Media.DATA);
            int bucketDisplayNameIndex = cur.getColumnIndexOrThrow(Media.BUCKET_DISPLAY_NAME);
            int bucketIdIndex = cur.getColumnIndexOrThrow(Media.BUCKET_ID);
            /**
             * Description:这里增加了一个判断:判断照片的名字是否合法,例如.jpg .png    图片名字是不合法的,直接过滤掉
             */
            do {
                if (cur.getString(photoPathIndex).substring(
                        cur.getString(photoPathIndex).lastIndexOf("/")+1,
                        cur.getString(photoPathIndex).lastIndexOf("."))
                        .replaceAll(" ", "").length()<=0)
                {
                    Log.d(TAG, "出现了异常图片的地址:cur.getString(photoPathIndex)="+cur.getString(photoPathIndex));
                    Log.d(TAG, "出现了异常图片的地址:cur.getString(photoPathIndex).substring="+cur.getString(photoPathIndex)
                            .substring(cur.getString(photoPathIndex).lastIndexOf("/")+1,cur.getString(photoPathIndex).lastIndexOf(".")));
                }else {
                    String _id = cur.getString(photoIDIndex);
                    String path = cur.getString(photoPathIndex);
                    String bucketName = cur.getString(bucketDisplayNameIndex);
                    String bucketId = cur.getString(bucketIdIndex);
                    PhotoUpImageBucket bucket = bucketList.get(bucketId);
                    if (bucket == null) {
                        bucket = new PhotoUpImageBucket();
                        bucketList.put(bucketId, bucket);
                        bucket.imageList = new ArrayList<PhotoUpImageItem>();
                        bucket.bucketName = bucketName;
                    }
                    bucket.count++;
                    PhotoUpImageItem imageItem = new PhotoUpImageItem();
                    imageItem.setImageId(_id);
                    imageItem.setImagePath(path);
                    imageItem.setPhoto(true);
//                  imageItem.setThumbnailPath(thumbnailList.get(_id));
                    bucket.imageList.add(imageItem);
                    Log.i(TAG, "PhotoUpAlbumHelper类中 的——》path="+thumbnailList.get(_id));
                }
            } while (cur.moveToNext());
        }
        cur.close();
        hasBuildImagesBucketList = true;
    }

    /**
     * 得到图片集
     * @param refresh
     * @return
     */
    public List<PhotoUpImageBucket> getImagesBucketList(boolean refresh) {
        if (refresh || (!refresh && !hasBuildImagesBucketList)) {
            buildImagesBucketList();
        }
        List<PhotoUpImageBucket> tmpList = new ArrayList<PhotoUpImageBucket>();
        Iterator<Entry<String, PhotoUpImageBucket>> itr = bucketList.entrySet().iterator();
        while (itr.hasNext()) {
            Map.Entry<String, PhotoUpImageBucket> entry = (Map.Entry<String, PhotoUpImageBucket>) itr
                    .next();
            tmpList.add(entry.getValue());
        }
        PhotoUpImageBucket videoBucket= getVideoes();
        tmpList.add(videoBucket);
        return tmpList;
    }

    /**
     * 得到原始图像路径
     * @param image_id
     * @return
     */
    String getOriginalImagePath(String image_id) {
        String path = null;
        Log.i(TAG, "---(^o^)----" + image_id);
        String[] projection = { Media._ID, Media.DATA };
        Cursor cursor = cr.query(Media.EXTERNAL_CONTENT_URI, projection,
                Media._ID + "=" + image_id, null, Media.DATE_MODIFIED+" desc");
        if (cursor != null) {
            cursor.moveToFirst();
            path = cursor.getString(cursor.getColumnIndex(Media.DATA));
        }
        return path;
    }
    
    private PhotoUpImageBucket getVideoes(){
        PhotoUpImageBucket videoes = new PhotoUpImageBucket();
        List<PhotoUpImageItem> videoList = new ArrayList<PhotoUpImageItem>();
        int count = 0;
        String[] params = new String[]{MediaStore.Video.Media._ID
                ,MediaStore.Video.Media.DISPLAY_NAME,MediaStore.Video.Media.DATA};
        //获取游标
        Cursor cursor = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, params, null, null, null);
        //获取制定索引值
        int _id = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
        int _name = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
        int _path = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
        if (cursor.moveToFirst()) {
            do {
                if (cursor.getString(_path).substring(
                        cursor.getString(_path).lastIndexOf("/")+1,
                        cursor.getString(_path).lastIndexOf("."))
                        .replaceAll(" ", "").length()<=0)
                {
                    Log.d(TAG, "出现了异常视屏的地址:cur.getString(photoPathIndex)="+cursor.getString(_path));
                    Log.d(TAG, "出现了异常视屏的地址:cur.getString(photoPathIndex).substring="+cursor.getString(_path)
                            .substring(cursor.getString(_path).lastIndexOf("/")+1,cursor.getString(_path).lastIndexOf(".")));
                }else {
                    String id = cursor.getString(_id);
                    String path = cursor.getString(_path);
                    
                    PhotoUpImageItem video = new PhotoUpImageItem();
                    video.setImageId(id);
                    video.setImagePath(path);
                    video.setPhoto(false);
                    videoList.add(video);
                    count++;
                }
            } while (cursor.moveToNext());
            videoes.setCount(count);
            videoes.setBucketName(context.getString(R.string.video_file_name));
            videoes.setImageList(videoList);
        }
        return videoes;
    }
    public void destoryList()
    {
        thumbnailList.clear();
        thumbnailList = null;
        albumList.clear();
        albumList = null;
        bucketList.clear();
        bucketList = null;
    }

    public void setGetAlbumList(GetAlbumList getAlbumList) {
        this.getAlbumList = getAlbumList;
    }

    public interface GetAlbumList{
        public void getAlbumList(List<PhotoUpImageBucket> list);
    }

    @Override
    protected Object doInBackground(Object... params) {
        return getImagesBucketList((Boolean)(params[0]));
    }
    @SuppressWarnings("unchecked")
    @Override
    protected void onPostExecute(Object result) {
        super.onPostExecute(result);
        getAlbumList.getAlbumList((List<PhotoUpImageBucket>)result);
    }
    
}

其中用到了两个工具实体类:
PhotoUpImageBucket类

package com.example.test1.bean;

import java.io.Serializable;
import java.util.List;


/**
 * 一个目录下的相册对象
 */
public class PhotoUpImageBucket implements Serializable{
    
    public int count = 0;//相册中的图片数量
    public String bucketName;//相册名
    public List<PhotoUpImageItem> imageList;//相册中的图片集合
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public String getBucketName() {
        return bucketName;
    }
    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }
    public List<PhotoUpImageItem> getImageList() {
        return imageList;
    }
    public void setImageList(List<PhotoUpImageItem> imageList) {
        this.imageList = imageList;
    }
    
}

PhotoUpImageItem类

package com.example.test1.bean;

import java.io.Serializable;

/**
 * 相册下的图片或视屏对象
 */
public class PhotoUpImageItem implements Serializable {

    //图片ID
    private String imageId;
    //原图路径
    private String imagePath;
    //是否被选择
    private boolean isSelected = false;
    //图片还是视屏     true为图片   false为视屏
    private boolean isPhoto = true;
    
    public String getImageId() {
        return imageId;
    }
    public void setImageId(String imageId) {
        this.imageId = imageId;
    }
    public String getImagePath() {
        return imagePath;
    }
    public void setImagePath(String imagePath) {
        this.imagePath = imagePath;
    }
    public boolean isSelected() {
        return isSelected;
    }
    public void setSelected(boolean isSelected) {
        this.isSelected = isSelected;
    }
    public boolean isPhoto() {
        return isPhoto;
    }
    public void setPhoto(boolean isPhoto) {
        this.isPhoto = isPhoto;
    }
    
    
}

二、新建一个activity,在其中放置一个GridView用于存放相册集合

package com.example.test1;

import java.util.HashMap;
import java.util.List;

import com.example.test1.adpater.AlbumsAdapter;
import com.example.test1.bean.PhotoUpImageBucket;
import com.example.test1.util.PhotoUpAlbumHelper;
import com.example.test1.util.PhotoUpAlbumHelper.GetAlbumList;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;

public class AlbumsActivity extends Activity implements OnScrollListener{

    private GridView gridView;
    private AlbumsAdapter adapter;
    private PhotoUpAlbumHelper photoUpAlbumHelper;
    private List<PhotoUpImageBucket> list;
    public static HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.albums_gridview);
        init();
        loadData();
        onItemClick();
    }
    private void init(){
        gridView = (GridView) findViewById(R.id.album_gridv);
        adapter = new AlbumsAdapter(AlbumsActivity.this);
        gridView.setAdapter(adapter);
    }
    
    private void loadData(){
        photoUpAlbumHelper = PhotoUpAlbumHelper.getHelper();
        photoUpAlbumHelper.init(AlbumsActivity.this);
        photoUpAlbumHelper.setGetAlbumList(new GetAlbumList() {
            @Override
            public void getAlbumList(List<PhotoUpImageBucket> list) {
                adapter.setArrayList(list);
                adapter.notifyDataSetChanged();
                AlbumsActivity.this.list = list;
            }
        });
        photoUpAlbumHelper.execute(false);
    }
    
        //设置gridView的item点击事件
    private void onItemClick(){
        gridView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                Intent intent = new Intent(AlbumsActivity.this,AlbumItemActivity.class);
                intent.putExtra("imagelist", list.get(position));
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    
    //释放图片的函数  
    private void recycleBitmapCaches(int fromPosition,int toPosition){                 
            Bitmap delBitmap = null;  
            for(int del=fromPosition;del<toPosition;del++){  
                    delBitmap = bitmaps.get(list.get(del).getBucketName());          
                    if(delBitmap != null){          
                            //如果非空则表示有缓存的bitmap,需要清理          
                            //从缓存中移除该del->bitmap的映射                 
                            bitmaps.remove(list.get(del).getBucketName());                 
                            delBitmap.recycle();          
                            delBitmap = null;  
                    }  
            }                 
    } 
    
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        
    }
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        //注释:firstVisibleItem为第一个可见的Item的position,从0开始,随着拖动会改变  
        //visibleItemCount为当前页面总共可见的Item的项数  
        //totalItemCount为当前总共已经出现的Item的项数 
        recycleBitmapCaches(0,firstVisibleItem);
        recycleBitmapCaches(firstVisibleItem+visibleItemCount,totalItemCount);
        
    }
}

为GridView定义适配器AlbumsAdapter

package com.example.test1.adpater;

import java.util.ArrayList;
import java.util.List;

import com.example.test1.AlbumsActivity;
import com.example.test1.R;
import com.example.test1.bean.PhotoUpImageBucket;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.media.ThumbnailUtils;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class AlbumsAdapter extends BaseAdapter {

    Context mContext;
    
    private List<PhotoUpImageBucket> arrayList;
    private LayoutInflater layoutInflater;
    private ImageLoader imageLoader = ImageLoader.getInstance();
    private DisplayImageOptions options;
    private String TAG = AlbumsAdapter.class.getSimpleName();
    public AlbumsAdapter(Context context){
        mContext = context;
        layoutInflater = LayoutInflater.from(context);
        arrayList = new ArrayList<PhotoUpImageBucket>();//初始化集合
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
        .threadPriority(Thread.NORM_PRIORITY - 2)
        .denyCacheImageMultipleSizesInMemory()
        .discCacheFileNameGenerator(new Md5FileNameGenerator())
        .tasksProcessingOrder(QueueProcessingType.LIFO)
        .memoryCacheExtraOptions(96, 120)
        .build();
        // Initialize ImageLoader with configuration.
        imageLoader.init(config);

        // 使用DisplayImageOption.Builder()创建DisplayImageOptions
        options = new DisplayImageOptions.Builder()
                .showStubImage(R.drawable.album_default_loading_pic) // 设置图片下载期间显示的图片
                .showImageForEmptyUri(R.drawable.album_default_loading_pic) // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.drawable.album_default_loading_pic) // 设置图片加载或解码过程中发生错误显示的图片
                .cacheInMemory(true) // 设置下载的图片是否缓存在内存中
                .cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
                // .displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片
                .bitmapConfig(Config.RGB_565)
                .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
                .build(); // 创建配置过的DisplayImageOption对象
        
    };
    @Override
    public int getCount() {
        return arrayList.size();
    }

    @Override
    public Object getItem(int position) {
        return arrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final Holder holder;
        
        if (convertView == null) {
            holder = new Holder();
            convertView = layoutInflater.inflate(R.layout.ablums_adapter_item, parent, false);
            holder.image = (ImageView) convertView.findViewById(R.id.image);
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.count = (TextView) convertView.findViewById(R.id.count);
            convertView.setTag(holder);
        }else {
            holder = (Holder) convertView.getTag();
        }
        holder.count.setText(""+arrayList.get(position).getCount());
        holder.name.setText(arrayList.get(position).getBucketName());
        
        Log.e("aaaaaaaaaaaaaaaaaaaaaa", "con:"+mContext.getString(R.string.video_file_name)+"   list:"+arrayList.get(position).getBucketName()+"   position:"+position);
        if ((mContext.getString(R.string.video_file_name)).equals(
                arrayList.get(position).getBucketName())) {//如果是视屏,则起一个线程获取缩略图
            holder.image.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album_default_loading_pic));
            final Handler mhHandler = new Handler(){

                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                    case 111:
                        Bitmap bitmap = (Bitmap) msg.obj;
                        holder.image.setImageBitmap(bitmap);
                        AlbumsActivity.bitmaps.put(arrayList.get(position).getBucketName(), bitmap);
                        break;

                    default:
                        break;
                    }
                    super.handleMessage(msg);
                    
                }
                
            };
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    String videoPath = arrayList.get(position).getImageList().get(0).getImagePath();
                    Bitmap bitmap= ThumbnailUtils.createVideoThumbnail(
                            videoPath,MediaStore.Video.Thumbnails.MINI_KIND);
                    Message msg = new Message();
                    msg.what=111;
                    msg.obj=bitmap;
                    mhHandler.sendMessage(msg);
                }
            }).start();
//          
            
        }else {
            imageLoader.displayImage("file://"+arrayList.get(position).getImageList().get(0).getImagePath(),
                    holder.image, options);
        }
        
        return convertView;
    }
    

    class Holder{
        ImageView image;
        TextView name;
        TextView count;
    }

    public void setArrayList(List<PhotoUpImageBucket> arrayList) {
        this.arrayList = arrayList;
    }
}

在这里加载图片使用的时imageloader实现加载,以解决GridView加载图片卡顿及内存问题

三、然后是进入相册后图片列表的activity

首先是albm_item_images.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffffff" >
    <RelativeLayout 
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#ff78ccf2">
        <TextView 
            android:id="@+id/back"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="10dp"
            android:textColor="#ffffff"
            android:textSize="14sp"
            android:text="@android:string/cancel"/>
        <TextView 
            android:id="@+id/sure"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:textColor="#ffffff"
            android:textSize="14sp"
            android:text="@android:string/yes"/>
    </RelativeLayout>
    <GridView
        android:id="@+id/album_item_gridv"
        android:listSelector="@android:color/transparent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/title"
        android:horizontalSpacing="8dp"
        android:verticalSpacing="20dp"
        android:numColumns="3" 
        android:layout_marginTop="10dp"
        android:layout_centerHorizontal="true"
        />

</RelativeLayout>

AlbumItemActivity,显示图片的界面

import com.example.test1.bean.PhotoUpImageBucket;
import com.example.test1.bean.PhotoUpImageItem;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;

public class AlbumItemActivity extends Activity implements OnClickListener, OnScrollListener{

    private GridView gridView;
    private TextView back,ok;
    private PhotoUpImageBucket photoUpImageBucket;
    private ArrayList<PhotoUpImageItem> selectImages;
    private AlbumItemAdapter adapter;
    public static HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.album_item_images);
        init();
        setListener();
    }
    private void init(){
        gridView = (GridView) findViewById(R.id.album_item_gridv);
        back = (TextView) findViewById(R.id.back);
        ok = (TextView) findViewById(R.id.sure);
        selectImages = new ArrayList<PhotoUpImageItem>();
        
        Intent intent = getIntent();
        photoUpImageBucket = (PhotoUpImageBucket) intent.getSerializableExtra("imagelist");
        adapter = new AlbumItemAdapter(photoUpImageBucket.getImageList(), AlbumItemActivity.this);
        gridView.setAdapter(adapter);
    }
    private void setListener(){
        back.setOnClickListener(this);
        ok.setOnClickListener(this);
        gridView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                if (photoUpImageBucket.getImageList().get(position).isPhoto()) {//如果是图片的话
                    
                    CheckBox checkBox = (CheckBox) view.findViewById(R.id.check);
                    photoUpImageBucket.getImageList().get(position).setSelected(
                            !checkBox.isChecked());
                    adapter.notifyDataSetChanged();
                    
                    Toast.makeText(AlbumItemActivity.this, "postion="+position, 
                            Toast.LENGTH_SHORT).show();
//                  photoUpImageBucket.getImageList().get(position).setSelected(
//                          !photoUpImageBucket.getImageList().get(position).isSelected());
//                  adapter.notifyDataSetChanged();
                    if (photoUpImageBucket.getImageList().get(position).isSelected()) {
                        if (selectImages.contains(photoUpImageBucket.getImageList().get(position))) {
                            
                        }else {
                            selectImages.add(photoUpImageBucket.getImageList().get(position));
                        }
                    }else {
                        if (selectImages.contains(photoUpImageBucket.getImageList().get(position))) {
                            selectImages.remove(photoUpImageBucket.getImageList().get(position));
                        }else {
                            
                        }
                    }
                }else {//如果是视屏的话
                    Toast.makeText(AlbumItemActivity.this, "跳转页面,展示视屏", Toast.LENGTH_SHORT).show();
                }
                
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.back:
            finish();
            break;
        case R.id.sure:
//          Intent intent = new Intent(AlbumItemActivity.this,SelectedImagesActivity.class);
//          intent.putExtra("selectIma", selectImages);
//          startActivity(intent);
            break;

        default:
            break;
        }
    }
    //释放图片的函数  
    private void recycleBitmapCaches(int fromPosition,int toPosition){                 
            Bitmap delBitmap = null;  
            for(int del=fromPosition;del<toPosition;del++){  
                    delBitmap = bitmaps.get(photoUpImageBucket.getImageList().get(del).getImageId());          
                    if(delBitmap != null){          
                            //如果非空则表示有缓存的bitmap,需要清理          
                            //从缓存中移除该del->bitmap的映射                 
                            bitmaps.remove(photoUpImageBucket.getImageList().get(del).getImageId());                 
                            delBitmap.recycle();          
                            delBitmap = null;  
                    }  
            }                 
    } 
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        
    }
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        //注释:firstVisibleItem为第一个可见的Item的position,从0开始,随着拖动会改变  
        //visibleItemCount为当前页面总共可见的Item的项数  
        //totalItemCount为当前总共已经出现的Item的项数 
        recycleBitmapCaches(0,firstVisibleItem);
        recycleBitmapCaches(firstVisibleItem+visibleItemCount,totalItemCount);
    }

}

具体的图片或者视屏的GridView的适配器

package com.example.test1.adpater;

import java.util.HashMap;
import java.util.List;

import com.example.test1.AlbumsActivity;
import com.example.test1.R;
import com.example.test1.bean.PhotoUpImageItem;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.media.ThumbnailUtils;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;

public class AlbumItemAdapter extends BaseAdapter {
    private List<PhotoUpImageItem> list;
    private LayoutInflater layoutInflater;
    private ImageLoader imageLoader;
    private DisplayImageOptions options;
    private Context mContext;
    private HashMap<Integer, Holder> holderMaps = new HashMap<Integer, AlbumItemAdapter.Holder>();
    public AlbumItemAdapter(List<PhotoUpImageItem> list,Context context){
        this.list = list;
        mContext = context;
        layoutInflater = LayoutInflater.from(context);
        imageLoader = ImageLoader.getInstance();
        // 使用DisplayImageOption.Builder()创建DisplayImageOptions
        options = new DisplayImageOptions.Builder()
                .showStubImage(R.drawable.album_default_loading_pic) // 设置图片下载期间显示的图片
                .showImageForEmptyUri(R.drawable.album_default_loading_pic) // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.drawable.album_default_loading_pic) // 设置图片加载或解码过程中发生错误显示的图片
                .cacheInMemory(true) // 设置下载的图片是否缓存在内存中
                .cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
                // .displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片
                .bitmapConfig(Config.ARGB_8888)
                .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
                .build(); // 创建配置过的DisplayImageOption对象
    }
    
    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final Holder holder;
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.album_item_images_item_view, parent, false);
            holder = new Holder();
            holder.imageView = (ImageView) convertView.findViewById(R.id.image_item);
            holder.checkBox = (CheckBox) convertView.findViewById(R.id.check);
            holder.videPlay = (ImageView) convertView.findViewById(R.id.video_play);
            convertView.setTag(holder);
            holderMaps.put(position, holder);
        }else {
            holder = (Holder) convertView.getTag();
            holderMaps.put(position, holder);
        }
        if (list.get(position).isPhoto()) {
            //图片加载器的使用代码,就这一句代码即可实现图片的加载。请注意
            //这里的uri地址,因为我们现在实现的是获取本地图片,所以使
            //用"file://"+图片的存储地址。如果要获取网络图片,
            //这里的uri就是图片的网络地址。
            imageLoader.displayImage("file://"+list.get(position).getImagePath(), holder.imageView, options);
            holder.checkBox.setChecked(list.get(position).isSelected());
            holder.videPlay.setVisibility(View.GONE);
        }else {
            holder.imageView.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album_default_loading_pic));
            final Handler mhHandler = new Handler(){

                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                    case 111:
                        Bitmap bitmap = (Bitmap) msg.obj;
                        int num = msg.arg1;
                        Holder mHolder= holderMaps.get(num);
                        if (bitmap!=null) {
                            mHolder.imageView.setImageBitmap(bitmap);
                            AlbumsActivity.bitmaps.put(list.get(position).getImageId(), bitmap);
                        }
                        mHolder.videPlay.setVisibility(View.VISIBLE);
                        mHolder.checkBox.setVisibility(View.GONE);
                        break;

                    default:
                        break;
                    }
                    super.handleMessage(msg);
                    
                }
                
            };
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    String videoPath = list.get(position).getImagePath();
                    Bitmap bitmap= ThumbnailUtils.createVideoThumbnail(
                            videoPath,MediaStore.Video.Thumbnails.MINI_KIND);
//                  if (bitmap!=null) {
//                      holder.imageView.setImageBitmap(bitmap);
//                      AlbumsActivity.bitmaps.put(list.get(position).getImageId(), bitmap);
//                  }
//                  holder.videPlay.setVisibility(View.VISIBLE);
//                  holder.checkBox.setVisibility(View.GONE);
                    Message msg = new Message();
                    msg.what=111;
                    msg.obj=bitmap;
                    msg.arg1=position;
                    mhHandler.sendMessage(msg);
                }
            }).start();
        }
        
        return convertView;
    }
    
    class Holder{
        ImageView imageView;
        CheckBox checkBox;
        ImageView videPlay;
    }
}

需要注意的是,在数据库中查询道德视屏时没有缩略图的uri的,所以我们适配时的适配展示图需要用

Bitmap bitmap= ThumbnailUtils.createVideoThumbnail(
                            videoPath,MediaStore.Video.Thumbnails.MINI_KIND);

来获取缩略图,但因为imageloader加载图片时用url进行记载的。
我们加载视屏缩略图时要使用setImageBitmap(Bitmap)方法,那么我们就还需要释放我们的资源:

AlbumsActivity.bitmaps.put(arrayList.get(position).getBucketName(), bitmap);

    //释放图片的函数  
    private void recycleBitmapCaches(int fromPosition,int toPosition){                 
            Bitmap delBitmap = null;  
            for(int del=fromPosition;del<toPosition;del++){  
                    delBitmap = bitmaps.get(list.get(del).getBucketName());          
                    if(delBitmap != null){          
                            //如果非空则表示有缓存的bitmap,需要清理          
                            //从缓存中移除该del->bitmap的映射                 
                            bitmaps.remove(list.get(del).getBucketName());                 
                            delBitmap.recycle();          
                            delBitmap = null;  
                    }  
            }                 
    }
        @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        //注释:firstVisibleItem为第一个可见的Item的position,从0开始,随着拖动会改变  
        //visibleItemCount为当前页面总共可见的Item的项数  
        //totalItemCount为当前总共已经出现的Item的项数 
        recycleBitmapCaches(0,firstVisibleItem);
        recycleBitmapCaches(firstVisibleItem+visibleItemCount,totalItemCount);
        
    }

总结:
在实现获取相册中的图片或视频时需要注意的几点是:

  1. 在加载时要放在异步线程中执行,否在可能会导致ART。
  2. 加载图片使用imageloader以解决缓存及卡顿问题。
  3. 当要展示视频缩略图时需要自己生成Bitmap对象并加载,这是要注意释放资源。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容