仿微信選擇圖片之——加載內存中所有圖片

本文采用了結合LruCache內存緩存方式,LruCache介紹請看:http://blog.csdn.net/guolin_blog/article/details/9316683

第一步:加載硬盤中的圖片

Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = context.getContentResolver().query(mImageUri,null,MediaStore.Images.Media.MIME_TYPE+"=? or "+MediaStore.Images.Media.MIME_TYPE+"=?",new String[]{"image/png","image/jpeg"},null);
獲取到硬盤中的圖片地址

②逐一讀取並分類

下面貼出整體代碼

public class ContentResolvePic {
    private static HashMap<String,ArrayList<String>> mGroupMap = null;
    public static void getPicMap(final Context context, final GetPicCallback callback){
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                callback.callback(mGroupMap);//如果讀取成功回調返回
            }
        };
        if(mGroupMap == null){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mGroupMap = new HashMap<String, ArrayList<String>>();
                    Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    Cursor cursor = context.getContentResolver().query(mImageUri,null,MediaStore.Images.Media.MIME_TYPE+"=? or "+MediaStore.Images.Media.MIME_TYPE+"=?"
                            ,new String[]{"image/png","image/jpeg"},null);
                    while (cursor.moveToNext()){
                        String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));//這裏將各個相冊分類
                        if(!mGroupMap.containsKey("all")){
                            ArrayList<String> allList = new ArrayList<String>();
                            mGroupMap.put("all",allList);
                        }
                        mGroupMap.get("all").add(0,path);
                        File pathFile = new File(path);
                        String parentName = pathFile.getParentFile().getName();
                        if(!mGroupMap.containsKey(parentName)){
                            ArrayList<String> list = new ArrayList<String>();
                            mGroupMap.put(parentName,list);
                        }
                        mGroupMap.get(parentName).add(0,path);
                    }
                    cursor.close();
                    handler.sendEmptyMessage(0x123);
                }
            }).start();
        }else {
            callback.callback(mGroupMap);
        }
    }
    interface GetPicCallback{
        void callback(HashMap<String,ArrayList<String>> hashMap);
    }
}
這個類封裝用來獲取硬盤中的圖片信息。
第二步:指定緩衝區,幫助我們緩存圖片
/**
 * Created by rudy on 2015/8/26.
 * 這個類用來將圖片信息緩存到內存中
 */
public class NativeImageLoader {
    //指定線程池
    ExecutorService loadImageThreadPool = Executors.newFixedThreadPool(3);
    public static LruCache<String,Bitmap> mMemoryCache;//緩存區
    private boolean load = true; //指定是否可以加載圖片,這裏是在滑動的時候可以暫停加載
    private NativeImageLoader(){
        //指定緩存區的大小
        long maxMemory = Runtime.getRuntime().maxMemory()/1024;
        final int cacheSize = (int)maxMemory/4;
        mMemoryCache = new LruCache<String,Bitmap>(cacheSize){
            //計算bitmap的大小
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getByteCount()/1024;
            }

//            @Override
//            protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
//                super.entryRemoved(evicted, key, oldValue, newValue);
//                mMemoryCache.remove(key);
//                oldValue.recycle();
//                oldValue = null;
//            }
        };
    }
    private static NativeImageLoader nativeImageLoader=null;
    public static NativeImageLoader getInstance(){
        if(null == nativeImageLoader){
            synchronized (NativeImageLoader.class){
                if(null == nativeImageLoader){
                    nativeImageLoader =   new NativeImageLoader();
                }
            }
        }
        return nativeImageLoader;
    }
    //方法重載 加載圖片通過path
    public Bitmap loadNativeImage(String path,ImageLoadCallback callback){
       return this.loadNativeImage(path,null,callback);
    }
    //方法重載 加載圖片通過path,並指定縮放倍數
    public Bitmap loadNativeImage(final String path, final Point mpoint, final ImageLoadCallback imageLoadCallback){
        Bitmap bitmap = null;
        if(load){
            bitmap = getBitmapFromMemoryCache(path);

            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    imageLoadCallback.callback(path, (Bitmap) msg.obj);
                }
            };
            if(bitmap ==null){
                loadImageThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        Bitmap bitmap;
//                        bitmap = decodeSampledBitmapFromPath(path, mpoint == null ? 0 : mpoint.x, mpoint == null?0:mpoint.y);
                        bitmap = ImageUtil.getBitmapFromPathWithRequest(path, mpoint == null ? 0 : mpoint.x, mpoint == null?0:mpoint.y);
                        Message msg = handler.obtainMessage();
                        msg.obj = bitmap;
                        addBitmapToMemoryCache(path,bitmap);
                        handler.sendMessage(msg);
                    }
                });
            }
            }
        return  bitmap;
    }
    public static void addBitmapToMemoryCache(String path,Bitmap bitmap){
        if(getBitmapFromMemoryCache(path)==null&&bitmap!=null){
            synchronized (mMemoryCache) {
                mMemoryCache.put(path, bitmap);
            }
        }
    }
    public static Bitmap getBitmapFromMemoryCache(String path){
        synchronized (mMemoryCache) {
            return mMemoryCache.get(path);
        }
    }
    public interface ImageLoadCallback{
       void callback(String path, Bitmap bitmap);
    }
    public void stopLoadImage(boolean load){
        this.load = load;
    }
}

上面的ImageUtil類,是一個自己封裝的圖片工具類 用來放大或縮小我們的Bitmap,合理運用內存

/**
 * Created by rudy on 2015/9/2.
 *這個類是爲了計算Bitmap的縮放而獲得縮放後的Bitmap
 */
public class ImageUtil {
    private static ImageUtil imageUtil = null;
    private static ImageUtil getInstance(){
        if(null == imageUtil){
            synchronized (ImageUtil.class){
                if(null == imageUtil){
                    imageUtil = new ImageUtil();
                }
            }
        }
        return imageUtil;
    }
    private  int calculateInSampleSize(BitmapFactory.Options options,int reqHeight,int reqWidth){
        int sampleSize = 1;
        int picHeight = options.outHeight;
        int picWidth = options.outWidth;
        return calculateInSampleSize(reqHeight, reqWidth, sampleSize, picHeight, picWidth);
    }
    //計算縮放倍數
    private int calculateInSampleSize(int reqHeight, int reqWidth, int sampleSize, int picHeight, int picWidth) {
        if(picHeight>reqHeight && picWidth>reqWidth){
            sampleSize = picHeight>picWidth?picWidth/reqWidth:picHeight/reqHeight;
        }
        return sampleSize;
    }

    //加載Bitmap
    private Bitmap decodeSampledBitmapFromPath(String path,int reqHeight,int reqWidth){
        Bitmap bitmap = null;
        BitmapFactory.Options options =new BitmapFactory.Options();
        if(reqHeight!=0&&reqWidth!=0){
            options.inJustDecodeBounds = true;//這是表示不分配內存的
            BitmapFactory.decodeFile(path,options);
            options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
            options.inJustDecodeBounds = false;
        }
        bitmap = BitmapFactory.decodeFile(path,options);
        return  bitmap;
    }
    private Bitmap decodeSampledBitmapFromByte(byte[] bytes,int reqHeight,int reqWidth){
        Bitmap bitmap = null;
        BitmapFactory.Options options =new BitmapFactory.Options();
        if(reqHeight!=0&&reqWidth!=0){
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
            options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
            options.inJustDecodeBounds = false;
        }
        BitmapFactory.decodeByteArray(bytes,0,bytes.length,options);
        return  bitmap;
    }
    public static Bitmap getBitmapFromPathWithRequest(String path,int reqHeight,int reqWidth){
        return getInstance().decodeSampledBitmapFromPath(path,reqHeight,reqHeight);
    }
}

所需要的工具類已經寫好,下一步就是進行顯示。也就是制定適配器

貼一下代碼:

/**
 * Created by rudy on 2015/8/26.
 */
public class GalleryAdapter extends BaseAdapter implements AbsListView.OnScrollListener {
    private Context context;
    private Point mpoint = new Point(160,160);
    private GridView gallery;
    private ArrayList<String> list;
    private LayoutInflater inflater;
//    private NativeImageLoader imageLoader;
    private int firstItem,visibleItem;
    private HashMap<Integer,Boolean> mSelectItem = new HashMap<Integer,Boolean>();
    public GalleryAdapter(Context context,ArrayList<String> list,GridView gallery){
        inflater = LayoutInflater.from(context);
        this.context = context;
        this.list = list;
        this.gallery = gallery;
//        imageLoader = NativeImageLoader.getInstance();
        gallery.setOnScrollListener(this);
    }
    @Override
    public int getCount() {
        return list.size();
    }

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

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        String path = list.get(position);
        MyImageView imageView=null;
        ViewHolder viewHolder = null;
        if(convertView == null){
            convertView = inflater.inflate(R.layout.content_layout,null);
            viewHolder = new ViewHolder();
            viewHolder.imageView = (MyImageView)convertView.findViewById(R.id.image);
            viewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.checkbox);
            viewHolder.chooseView =(MyImageView) convertView.findViewById(R.id.choose_pic);
            convertView.setTag(viewHolder);
            viewHolder.imageView.setOnMeasureListener(new MyImageView.OnMeasureListener() {
                @Override
                public void onMeasureSize(int width, int height) {
                    mpoint.set(width/2,height/2);
                }
            });
        }else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        imageView = viewHolder.imageView;
        final View chooseView = viewHolder.chooseView;
        viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mSelectItem.put(position,isChecked);
                chooseView.setSelected(isChecked);
            }
        });
        viewHolder.checkBox.setChecked(mSelectItem.containsKey(position) ? mSelectItem.get(position) : false);
        chooseView.setSelected(mSelectItem.containsKey(position)?mSelectItem.get(position):false);
        imageView.setTag(path);
        setBitMap(path,imageView);
        return convertView;
    }
    private void setBitMap(String path,ImageView imageView){
        Bitmap bitmap = NativeImageLoader.getInstance().loadNativeImage(path, mpoint, new NativeImageLoader.ImageLoadCallback() {
            @Override
            public void callback(String path, Bitmap bitmap) {
                MyImageView imageView1 = (MyImageView) gallery.findViewWithTag(path);
                if (imageView1 != null && path != null && bitmap != null) {
                    imageView1.setImageBitmap(bitmap);
                }
            }
        });
        if(bitmap == null){
            imageView.setImageResource(R.mipmap.pic);
        }else {
            imageView.setImageBitmap(bitmap);
        }
    }
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE){
            NativeImageLoader.getInstance().stopLoadImage(true);
            for (int i = firstItem;i<firstItem+visibleItem;i++){
                setBitMap(list.get(i),(ImageView) gallery.findViewWithTag(list.get(i)));
            }
        }
        if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING){
            NativeImageLoader.getInstance().stopLoadImage(false);
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if(firstVisibleItem!=0){
//            imageLoader.stopLoadImage(false);
        }
        firstItem = firstVisibleItem;
        visibleItem = visibleItemCount;
    }

    class ViewHolder{
        public CheckBox checkBox;
        public MyImageView imageView;
        public MyImageView chooseView;
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章