图片加载器

图片加载器:

1 最重要的为ImageLoader类 :

/**
 * 保证了图片压缩,缓存和正常加载
 * @author micro
 *
 */
 public class ImageLoader {

    /**
     * 图片缓存空间
     */
    private LruCache<String, Bitmap> mLruCache;
    //线程池
    private ExecutorService mThreadPools;
    private static final int DEFAULT_THREAD_COUNT = 1;

    /**
     * 队列的调度方式,也就是图片的显示方式
     */
    private Type mType = Type.LIFO;

    /**
     * Runnable任务队列
     */
    private LinkedList<Runnable> mTaskQuene;

    /**
     * 轮询线程hanlder+Looper+Message
     */
    private Thread mPoolThread;
    private Handler mPoolThreadHandler;

    /**
     * UI处理线程
     */
    private Handler mUIHandler;
    /**
     * 图片显示的方法
     * LIFO拉到哪里,哪里就显示
     * FIFO表示从第一张开始显示
     */
    public enum Type{
        LIFO,FIFO
    }

    //信号量,防止并发的类,保证Handler不为NUll
    /* a semaphore maintains a set of permits.
     * Each acquire() blocks if necessary until a permit is available,
     *  and then takes it. Each release() adds a permit,
     *  potentially releasing a blocking acquirer.
     *  However, no actual permit objects are used;
     *   the Semaphore just keeps a count of the number available
     *   and acts accordingly. */
    private Semaphore mSemaphorePoolTreadHandler = new Semaphore(0);

    //保证线程池的正常执行和运行
    private Semaphore mSemaphoreThreadPool ;

    private static ImageLoader imageLoaderInstance;

    //ImageLoader
    private ImageLoader(int threadCount,Type type){

        init(threadCount,type);

    }

    /**
     * 初始化变量
     * @param threadCount
     * @param type
     */
    private void init(int threadCount, Type type) {
        // TODO Auto-generated method stub

        //
        mPoolThread = new Thread(){
            @Override
            public void run() {

                Looper.prepare();

                mPoolThreadHandler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        // TODO Auto-generated method stub

                        //线程池取出一个任务执行
                        mThreadPools.execute(getTask());

                        try {
                            mSemaphoreThreadPool.acquire();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block

                        }

                    }

                };
                //release一个信号量
                mSemaphorePoolTreadHandler.release();
                Looper.loop();
            }
        };
        //开启线程
        mPoolThread.start();

        //初始化缓存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();

        int cacheMemory = maxMemory/8;

        mLruCache = new LruCache<String, Bitmap>(cacheMemory){

            @Override
            protected int sizeOf(String key, Bitmap value) {
                //测量每一个Bitmap的大小
                // TODO Auto-generated method stub
                return value.getRowBytes()*value.getHeight();
                //字节数*高度
            }
        };  

        //创建线程池
        mThreadPools = Executors.newFixedThreadPool(threadCount);

        mTaskQuene = new LinkedList<Runnable>();
        mType = type;

        //初始化
        mSemaphoreThreadPool = new Semaphore(threadCount);

    }

    //单例模式
    //这样判断的好处就是使得效率提高
    public static ImageLoader getInstance(int threadCount,Type type){

        if(imageLoaderInstance==null){

            synchronized (ImageLoader.class) {

                if(imageLoaderInstance==null){

                    //这里开启了轮询线程
                    imageLoaderInstance = new ImageLoader(threadCount,type);
                }

            }
        }

        return imageLoaderInstance;

    }

    /**
     * 加载图片
     * @param path
     * @param imageView
     */

    public void loadImage(final String path,final ImageView imageView){

        imageView.setTag(path);

        if(mUIHandler==null){

            mUIHandler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    // TODO Auto-generated method stub

                    //获取图片,为ImageView回调设置图片

                    //获取资源
                    ImageBeanHolder holder = (ImageBeanHolder) msg.obj;

                    String path = holder.path;
                    Bitmap bm = holder.bm;
                    ImageView imageView = holder.imageView;

                    //判断path与getTag存储路径进行比较,一致则显示出来
                    if(imageView.getTag().toString().equals(path)){

                        imageView.setImageBitmap(bm);
                    }

                }
            };
        }

        //在缓存中获取对应路径的图片
        Bitmap bm = getBitmapFromLrucache(path);

        //找到就
        if(bm!=null){
            //回调
            Message message = Message.obtain();

            //ImageBeanHoler避免错乱
            ImageBeanHolder holder = new ImageBeanHolder();
            holder.bm = bm;
            holder.path = path;
            holder.imageView = imageView;

            message.obj=holder;
            mUIHandler.sendMessage(message);
            //执行完毕之后再到UI线程做进一步处理
        }else{

            //找不到就添加任务到线程处理
            //addTasK里也发送到轮询线程处理
            addTask(new Runnable() {

                public void run() {

                    //加载图片
                    //1 获取图片的大小
                    ImageSize imageSize = getImageSize(imageView);
                    //2进行压缩
                    Bitmap bm = decodeSampledBitmapFromPath(path,imageSize.width,imageSize.height);
                    //3图片加载到缓存
                    addBitmaptoLrucache(path,bm);

                    //4回调
                    Message message = Message.obtain();

                    ImageBeanHolder holder = new ImageBeanHolder();
                    holder.bm = bm;
                    holder.path = path;
                    holder.imageView = imageView;

                    message.obj=holder;
                    mUIHandler.sendMessage(message);

                    mSemaphoreThreadPool.release();

                }

            });
        }

    }
    /**
     * 添加图片到缓存
     * @param path
     * @param bm
     */
    protected void addBitmaptoLrucache(String path, Bitmap bm) {
        // TODO Auto-generated method stub
        if(getBitmapFromLrucache(path)==null){

            if(bm!=null){
                mLruCache.put(path, bm);
            }
        }

    }

    /**
     * 图片压缩
     * @param path
     * @param width
     * @param height
     * @return
     */
    protected Bitmap decodeSampledBitmapFromPath(String path,
            int width, int height) {
        // TODO Auto-generated method stub
        //获取图片的宽和高,并不把图片加载到内存中
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        //比较图片与options的宽和高

        options.inSampleSize = calculateInSampleSize(options,width,height);

        //获取InSampleSize再次解析图片
        options.inJustDecodeBounds =false;

        Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        return bitmap;
    }

    /**
     * 根据需求和实际的宽和高计算inSampleSize
     * @param options
     * @param width
     * @param height
     * @return
     */
    private int calculateInSampleSize(Options options, int reqwidth, int reqheight) {
        // TODO Auto-generated method stub
        int width = options.outWidth;
        int height = options.outHeight;

        int inSampleSize =1 ;

        if(width>reqwidth || height>reqheight){
            int widthRadio = Math.round(width*1.0f/reqwidth);
            int heightRadio = Math.round(height*1.0f/reqheight);

            inSampleSize = Math.max(widthRadio, heightRadio);
        }

        return inSampleSize;
    }

    /**
     * 获取图片的大小
     * @param imageView
     * @return
     */
     protected ImageSize getImageSize(ImageView imageView) {

        ImageSize imageSize = new ImageSize();

        LayoutParams lp = imageView.getLayoutParams();

        //获取屏幕的参数
        DisplayMetrics displayMetrics =
                imageView.getContext().getResources().getDisplayMetrics();

        int width = imageView.getWidth();//获取实际宽度
//      int width = getImageViewFieldValue(imageView, "mMaxWidth");
//      

        if(width<=0){
            width = lp.width;//获取imageView在Layout中声明的宽度

        }
        if(width<=0){
            width = getImageViewFieldValue(imageView, "mMaxWidth"); //检查最大值
        }
        //最坏的情况下等于屏幕宽度
        if(width<=0){
            width = displayMetrics.widthPixels;
        }

        int height = imageView.getHeight();
//      int height = getImageViewFieldValue(imageView, "mMaxHeight");//获取实际高度

        if(height<=0){
            height = lp.height;//获取imageView在Layout中声明的高度

        }
        if(height<=0){

            height = getImageViewFieldValue(imageView, "mMaxHeight"); //发射获取检查最大值,避免了仅Api16可用的
        }
        //最坏的情况下等于屏幕高度
        if(height<=0){
            height = displayMetrics.heightPixels;
        }

        //
        imageSize.width = width;
        imageSize.height = height;

        return imageSize;
        // TODO Auto-generated method stub

    }
     /**
      * 通过反射获取ImageView的任意属性值
      * @param object
      * @param filedName
      * @return
      */
     private static int getImageViewFieldValue(Object object,String filedName){

         int value = 0;
         try {

             Field field = ImageView.class.getDeclaredField(filedName);
             field.setAccessible(true);

             int fieldValue = field.getInt(object);//获取字段值

             if(fieldValue>0 && fieldValue<Integer.MAX_VALUE){

                 value = fieldValue;
             }

        } catch (Exception e) {
            // TODO: handle exception
        }
        return value;

     }

    private class ImageSize{
        int width;
        int height;
    }

    /**
     * 从任务队列取出一个任务
     * @return
     */
    private Runnable getTask() {
        // TODO Auto-generated method stub
        if(mType==Type.FIFO){

            return mTaskQuene.removeFirst();
        }else if(mType==Type.LIFO){

            return mTaskQuene.removeLast();
        }
        return null;
    }

    /**
     * 找不到就添加任务到线程处理
     * @param runnable
     */
    private synchronized void addTask(Runnable runnable) {
        // TODO Auto-generated method stub
        mTaskQuene.add(runnable);
        //防止并发
        try {
            if(mPoolThreadHandler==null){
                mSemaphorePoolTreadHandler.acquire();
            }

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //发送到轮询线程Handler处理
        mPoolThreadHandler.sendEmptyMessage(0X110);

    }

    private Bitmap getBitmapFromLrucache(String path) {
        // TODO Auto-generated method stub
        return mLruCache.get(path);
    }

    private class ImageBeanHolder{
        Bitmap bm;
        String path;
        ImageView imageView;
    }

}

2 GridView的适配器

ViewHolder:
/**
 * 这里ViewHolder实现了对各个View的设置
 * 以及mConvertView的优化
 * @author micro
 *
 */

public class ViewHolder {

    /*SparseArray:
     * It is intended to be more memory efficient
     * than using a HashMap to map Integers to Objects, both because it avoids
     * auto-boxing keys and its data structure doesn‘t rely on an extra entry object
     * for each mapping.*/

    private  SparseArray<View> mViews;   //View集合,高效

    private int mPostion;                //position
    private View mConvertView;           //传入的View

    private ViewHolder(Context context,ViewGroup parent,int layoutId,
            int position){

        this.mPostion = position;
        this.mViews = new SparseArray<View>();
        this.mConvertView = LayoutInflater.
                from(context).inflate(layoutId,parent,false);
        mConvertView.setTag(this);

    }
    //获取ViewHolder
    public static ViewHolder get(Context context,View convertView,
            ViewGroup parent,int layoutId,int position){

        ViewHolder holder = null;
        if(convertView==null){

            holder = new ViewHolder(context, parent, layoutId, position);

        }else{
            holder = (ViewHolder)convertView.getTag();
            holder.mPostion = position;
        }

    return holder;

    }

    public View getConvertView(){
        return mConvertView;
    }

    /**
     * 通过资源iD获取View控件,如果为空,则加入mViews中
     * @param viewId
     * @return
     */

    public <T extends View> T getView(int viewId){

        View view = mViews.get(viewId);
        if(view==null){

            view = mConvertView.findViewById(viewId);
            mViews.put(viewId, view);

        }
        return (T) view;

    }

    /**
     * 给TextView赋值字符串
     * @param viewId
     * @param text
     * @return
     */
    public ViewHolder setText(int viewId,String text){

        TextView textView = getView(viewId);
        textView.setText(text);

        return this;
    }

    /**
     * 资源id设置ImageView
     * @param viewId
     * @param drawableId
     * @return
     */
    public ViewHolder setImagetResource(int viewId,int drawableId){
        ImageView view = getView(viewId);
        view.setImageResource(drawableId);
        return this;

    }

    /**
     * bitmap设置ImageView
     * @param viewId
     * @param bitmap
     * @return
     */
    public ViewHolder setImageBitmap(int viewId,Bitmap bitmap){
        ImageView view =getView(viewId);
        view.setImageBitmap(bitmap);
        return this;

    }
    /**
     * url设置ImageView
     * @param viewId
     * @param url
     * @return
     */
    public ViewHolder setImageByUrl(int viewId,String url){

        ImageLoader.getInstance(3, Type.LIFO).
        loadImage(url, (ImageView)getView(viewId));

        return this;

    }

    public int getPosition(){
        return mPostion;

    }

}

public abstract class CommonAdapter<T> extends BaseAdapter {

    protected LayoutInflater mInflater;
    protected Context mContext;
    protected List<T> mDatas;
    protected  int mItemLayoutId;

    //构造器对上面的变量初始化
    public CommonAdapter(Context context,List<T> datas,int ItemlayoutId){

        this.mContext = context;
        this.mDatas = datas;
        this.mItemLayoutId = ItemlayoutId;
        this.mInflater = LayoutInflater.from(context);

    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mDatas.size();
    }

    @Override
    public T getItem(int position) {
        // TODO Auto-generated method stub
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub

        final ViewHolder viewHolder = getViewHolder(position, convertView, parent);
        convert(viewHolder, getItem(position));
        return viewHolder.getConvertView();
    }

    //抽象方法
    public abstract void convert(ViewHolder holder,T item);

    private ViewHolder getViewHolder(int position, View convertView, ViewGroup parent){

        return ViewHolder.
                get(mContext, convertView, parent, mItemLayoutId, position);

    }

}

/**
 * GridView的最终适配器
 * @author micro
 *
 * @param <T>
 */

public class MyAdapter extends CommonAdapter<String> {

    //这个存储的就是图片的路径集合
    public static List<String> mSelectImage = new
            LinkedList<String>();

    //文件夹路径
    private String mDirPath;

    /**
     * 构造器初始化
     * @param context
     * @param datas
     * @param ItemlayoutId
     */
    public MyAdapter(Context context, List<String> datas, int ItemlayoutId
            ,String dirPath) {
        super(context, datas, ItemlayoutId);
        // TODO Auto-generated constructor stub
        mDirPath = dirPath;

    }

    /**
     * 通过重写这个方法来设置不同点击状态下的变化
     */
    @Override
    public void convert(final ViewHolder holder, final String item) {
        // TODO Auto-generated method stub

        //no pic
        holder.setImagetResource(R.id.id_item_image, R.drawable.pictures_no);
        //no selected
        holder.setImagetResource(R.id.id_item_image, R.drawable.pictures_selected);

        //设置图片
        holder.setImageByUrl(R.id.id_item_image, mDirPath+"/"+item);

        //获取两个控件,下面将进行设置
        final ImageView mImageView = holder.getView(R.id.id_item_image);
        final ImageView mSelect = holder.getView(R.id.id_item_select);

        mImageView.setColorFilter(null);

        mImageView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                //已经选择的图片
                if(mSelectImage.contains(mDirPath+"/"+item)){

                    mSelectImage.remove(mDirPath+"/"+item);
                    mSelect.setImageResource(R.drawable.picture_unselected);
                    mImageView.setColorFilter(null);
                }else{
                    //没有选择,则
                    mSelectImage.add(mDirPath+"/"+item);
                    mSelect.setImageResource(R.drawable.pictures_selected);
                    mImageView.setColorFilter(Color.parseColor("#77000000"));

                }

            }
        });

        /**
         * 已经选择过的图片,显示出选择过的效果
         */
        if(mSelectImage.contains(mDirPath + "/" + item)){
            mSelect.setImageResource(R.drawable.pictures_selected);
            mImageView.setColorFilter(Color.parseColor("#77000000"));
        }

    }

}

3 popWindow的使用

/**
 * 这个相当于一个Activity,不过这个是显示在一个Activity之上的
 * 这里的BasePopupWindowForListView只是提供了一个模板供子类继承其功能
 * 子类最终将完善其功能
 * @author micro
 * @param <T>
 *
 */

public abstract class BasePopupWindowForListView<T> extends PopupWindow {

    /**
     * 布局文件的最外层的View
     */
    protected View mContentView;
    protected Context mContext;

    //数据
    protected  List<T> mDatas;

    //构造器
    public BasePopupWindowForListView(View contentView,int width,int height,
            boolean focusable){
        this(contentView, width, height, focusable, null);

    }

    public BasePopupWindowForListView(View contentView,int width,int height,
            boolean focusable,List<T> mDatas){
        this(contentView, width, height, focusable,mDatas,new Object[0]);

    }

    public BasePopupWindowForListView(View contentView,int width,int height,
            boolean focusable,List<T> mDatas,Object... params){
        super(contentView, width, height, focusable);

        this.mContentView = contentView;
        mContext = contentView.getContext();

        if(mDatas!=null){
            this.mDatas = mDatas;
        }

        if(params!=null && params.length>0){
            beforeInitWeNeedSomeParams(params);
        }

        //popWindow一些属性设置
        setBackgroundDrawable(new BitmapDrawable());
        /* When touchable,
         * the window will receive touch events,
         * otherwise touch events will go to the
         * window below it. By default the window is touchable.*/
        setTouchable(true);//这个很重要
        setOutsideTouchable(true);
        setTouchInterceptor(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
                    dismiss();

                    return true;
                }
                return false;
            }
        });

        initViews();
        initEvent();
        inits();

    }

    protected  abstract  void beforeInitWeNeedSomeParams(Object[] params);

    protected  abstract void initViews();
    protected  abstract void initEvent();
    protected  abstract void inits();

    public View findViewById(int id){

        return mContentView.findViewById(id);

    }

    /**
     * dp -->px转化
     * @param context
     * @param dp
     * @return
     */
    protected static int dpToPx(Context context,int dp){

        return (int) (context.getResources().getDisplayMetrics().densityDpi*dp +0.5f);

    }

}

public class ListImageDirPopupWindow extends BasePopupWindowForListView<ImageFolder> {

    private ListView mListDir;

    public ListImageDirPopupWindow(View convertView, int width, int height,
            List<ImageFolder> datas) {
        super(convertView, width, height, true,datas);

    }

    @Override
    protected void beforeInitWeNeedSomeParams(Object[] params) {
        // TODO Auto-generated method stub

    }

    @Override
    protected void initViews() {
        // TODO Auto-generated method stub
        mListDir = (ListView)findViewById(R.id.id_list_dir);

        mListDir.setAdapter(new CommonAdapter<ImageFolder>(mContext,mDatas,
                R.layout.list_dir_item) {

                    @Override
                    public void convert(ViewHolder holder, ImageFolder item) {
                        // TODO Auto-generated method stub
                        holder.setText(R.id.id_dir_item_name, item.getName());

                        holder.setImageByUrl(R.id.id_dir_item_img,item.getFirstImagePath());

                        holder.setText(R.id.id_dir_item_count, item.getCount()+"张");

                    }
        });
    }

    /**
     * 图片文件夹选中监听接口
     * @author micro
     *
     */
    public interface OnImageDirSelected{

        void selected(ImageFolder folder);
    }

    public OnImageDirSelected onImageDirSelected;

    public void setOnImageDirSelected(OnImageDirSelected mOnImageDirSelected){

        this.onImageDirSelected = mOnImageDirSelected;

    }

    @Override
    protected void initEvent() {
        // TODO Auto-generated method stub

        //ListView的点击监听中调用了onImageDirSelected
        mListDir.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                // TODO Auto-generated method stub

                if(onImageDirSelected!=null){
                    onImageDirSelected.selected(mDatas.get(position));
                }

            }
        });

    }

    @Override
    protected void inits() {
        // TODO Auto-generated method stub

    }
}

4 一些常用的方法

获取屏幕的高度:

private int mScreenHeight;   //屏幕高度
//获取屏幕高度的方法
        DisplayMetrics outMetrics = new DisplayMetrics();

        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);

        mScreenHeight = outMetrics.heightPixels;
设置一些背景变暗:
//设置背景变暗
                WindowManager.LayoutParams  lp = getWindow().getAttributes();

                lp.alpha = 1.0f;

                getWindow().setAttributes(lp);

内容提供器:

Uri imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

                //获取一个内容提供器
                ContentResolver mContentResolver = MainActivity.this.getContentResolver();

                //查询
                Cursor cursor = mContentResolver.query(imageUri, null,
                        MediaStore.Images.Media.MIME_TYPE+"=? or "
                        +MediaStore.Images.Media.MIME_TYPE+"=?",
                        new String[]{"image/jpeg","image/png"},
                        MediaStore.Images.Media.DATE_MODIFIED);

5 最后的MainActivity:

public class MainActivity extends Activity {

    private ProgressDialog mProgressDialog;

    private int mPicsSize;        //图片数量

    private File mImgDir;          //图片数量最多的文件夹,将图片最多的文件夹显示

    private List<String> mImgs;     //文件夹下的所有图片

    private GridView mGridView;     

    private MyAdapter mMyaAdapter;    

    //临时的辅助类,防止同一文件夹的多次扫描
    private HashSet<String> mDirpaths = new HashSet<String>();  

    //扫描拿到的所有图片的文件夹
    private List<ImageFolder> mImageFolders = new ArrayList<ImageFolder>();

    private RelativeLayout mBottomly;

    private TextView mChooseDir;
    private TextView mImageCount;

    int totalCount = 0;

    private int mScreenHeight;   //屏幕高度

    private ListImageDirPopupWindow mListImageDirPopupWindow;

    //通知Handler扫描图片已完成,然后处理并初始化PopupWindw
    private Handler mHandler = new Handler(){

        public void handleMessage(android.os.Message msg) {

            mProgressDialog.dismiss();

            data2View();//最终将文件夹中图片最多的文件夹下的图片显示在一开始的主界面中

            initListDirPopupWindw();

        }
    };

    /**
     * 为View绑定数据
     */

    private void data2View() {
        // TODO Auto-generated method stub

        if( mImgDir==null ){
            Toast.makeText(getApplicationContext(), "您的手机没有图片",Toast.LENGTH_SHORT).show();
            return ;
        }

        mImgs = Arrays.asList(mImgDir.list());      //获取文件夹的所有图片文件

        mMyaAdapter = new MyAdapter(
                getApplicationContext(), mImgs,
                R.layout.grid_item, mImgDir.getAbsolutePath());

        mGridView.setAdapter(mMyaAdapter);

        mImageCount.setText(totalCount+"张");

    };

    /**
     * 初始化PopWindow
     */
    private void initListDirPopupWindw() {
        // TODO Auto-generated method stub

        //加载布局
        mListImageDirPopupWindow = new ListImageDirPopupWindow(LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_dir, null),
                LayoutParams.MATCH_PARENT, (int) (mScreenHeight*0.7), mImageFolders);
        //
        mListImageDirPopupWindow.setOnDismissListener(new OnDismissListener() {

            @Override
            public void onDismiss() {
                // TODO Auto-generated method stub

                //设置背景变暗
                WindowManager.LayoutParams  lp = getWindow().getAttributes();

                lp.alpha = 1.0f;

                getWindow().setAttributes(lp);

            }
        });

        // 设置选择文件夹的回调,点击监听,显示
        mListImageDirPopupWindow.setOnImageDirSelected(new OnImageDirSelected() {

            @Override
            public void selected(ImageFolder folder) {
                // TODO Auto-generated method stub
                mImgDir = new File(folder.getDir());

                //文件处理和过滤器
                mImgs = Arrays.asList(mImgDir.list(new FilenameFilter() {

                    @Override
                    public boolean accept(File dir, String filename) {

                        if(filename.endsWith(".jpg")||filename.endsWith(".png")||filename.endsWith(".jpeg")
                                ||filename.endsWith(".JPG") || filename.endsWith(".PNG")||
                                filename.endsWith(".JPEG")){

                            return true;

                        }
                        return false;
                    }
                }));

                //将图片显示出来
                mMyaAdapter = new MyAdapter(
                        getApplicationContext(), mImgs,
                        R.layout.grid_item, mImgDir.getAbsolutePath());
                mGridView.setAdapter(mMyaAdapter);

                mImageCount.setText(folder.getCount()+"张");
                mChooseDir.setText(folder.getName());
                mListImageDirPopupWindow.dismiss();

            }
        });

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        //获取屏幕高度的方法
        DisplayMetrics outMetrics = new DisplayMetrics();

        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);

        mScreenHeight = outMetrics.heightPixels;

        //初始化
        initViews();

        getImages();

        initEvent();
    }

    /**
     * 初始化事件
     */
    private void initEvent() {
        // TODO Auto-generated method stub
        mBottomly.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                //这里设置了一个淡出动画
                mListImageDirPopupWindow.
                setAnimationStyle(R.style.anim_popup_dir);
                //从底部弹出
                mListImageDirPopupWindow.showAsDropDown(mBottomly,0,0);

                //设置背景
                WindowManager.LayoutParams lp = getWindow().getAttributes();

                lp.alpha = .3f;

                getWindow().setAttributes(lp);

            }
        });

    }

    /**
     * 获取图片
     */
    private void getImages() {
        // TODO Auto-generated method stub
        if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){

            Toast.makeText(getApplicationContext(), "暂无外置存储", Toast.LENGTH_SHORT).show();

        }

        //显示进度Dialog
        mProgressDialog = ProgressDialog.show(this,null , "正在加载...");

        //运行在子线程中 完成图片的扫描,最终获得jpg最多的那个文件夹
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                String firstPath =null;

                Uri imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

                //获取一个内容提供器
                ContentResolver mContentResolver = MainActivity.this.getContentResolver();

                //查询
                Cursor cursor = mContentResolver.query(imageUri, null,
                        MediaStore.Images.Media.MIME_TYPE+"=? or "
                        +MediaStore.Images.Media.MIME_TYPE+"=?",
                        new String[]{"image/jpeg","image/png"},
                        MediaStore.Images.Media.DATE_MODIFIED);

                while(cursor.moveToNext()){

                    //获取图片路径
                    String path = cursor.getString(
                            cursor.getColumnIndex(MediaStore.Images.Media.DATA));

                    //拿到第一张图片的路径
                    if(firstPath==null){
                        firstPath = path;
                        Log.e("firstPath", "firstPath");
                    }

                    //获取该图片的父路径
                    File parentFile = new File(path).getParentFile();

                    if(parentFile==null){
                        continue;
                    }
                    String dirPath = parentFile.getAbsolutePath();

                    ImageFolder imageFolder =null;

                    // 利用一个HashSet防止多次扫描同一个文件夹

                    if(mDirpaths.contains(dirPath)){
                        continue;
                    }else{

                        mDirpaths.add(dirPath);

                        imageFolder = new ImageFolder();
                        imageFolder.setDir(dirPath);
                        imageFolder.setFirstImagePath(path);

                    }

                    int picSize = parentFile.listFiles(new FilenameFilter() {

                        @Override
                        public boolean accept(File dir, String filename) {
                            // TODO Auto-generated method stub

                            if(filename.endsWith(".png")
                                    || filename.endsWith(".jpg")
                                    || filename.endsWith(".jpeg")
                                    || filename.endsWith(".JPG")
                                    || filename.endsWith(".PNG")
                                    || filename.endsWith(".JPEG")){

                                return true;

                            }
                            return false;
                        }
                    }).length;

                    totalCount+=picSize;
                    imageFolder.setCount(picSize);
                    mImageFolders.add(imageFolder);

                    //获取了最多图片的文件夹
                    if(picSize>mPicsSize){
                        mPicsSize = picSize;
                        mImgDir = parentFile;
                    }

                }

                cursor.close();

                // 扫描完成,辅助的HashSet也就可以释放内存了
                mDirpaths = null;

                // 通知Handler扫描图片完成
                mHandler.sendEmptyMessage(0X110);

            }
        }).start();

    }

    private void initViews() {

        mGridView = (GridView)findViewById(R.id.id_gridview);
        mChooseDir = (TextView)findViewById(R.id.id_choose_dir);
        mImageCount = (TextView)findViewById(R.id.id_total_count);

        mBottomly = (RelativeLayout)findViewById(R.id.id_bottom_ly);

    }

}

6 效果显示:

7 感谢http://blog.csdn.net/lmj623565791/article/details/39943731所提供的参考

时间: 2024-10-25 04:31:30

图片加载器的相关文章

Android-异步图片加载器

在ListView中加载图片是非常常见的场景,图片的加载要满足下面的几个要求: (1)不管图片是位于网络还是本地,加载都不应该是同步的,而是应该异步去加载,比如用AsyncTask. (2)为了避免重复下载图片和页面展示的速度,一般要做缓存,比如最常见的LruCache. (3)为了提高Listview的性能,我们一般会用holder来重用Listview的item. 代码大概就是这样的: public class MainActivity extends Activity { private

Canvas---Canvas图像加载、利用javascript回调机制实现一个图片加载器

canvas的drawImage方法有个缺点,就是当图片还未加载完成时调用它将无效. 当然,在高速运转的游戏主循环中,可以直接忽略这个问题,或者用 img.complete == true来做下判断. 在游戏循环之外的地方,可以用 img.onload = function (){};这样的回调解决. 但是,如果需要实现预先大量图片的加载,并且将加载进度告知用户,这时就需要一个图片加载器. 一.图片加载器原理 1.对于每张图片,开启对应的一个线程去负责加载,加载完成后修改一个变量的值-loade

高性能异步图片加载器的JS库:lazysizes

<script src="lazysizes.min.js" async=""></script> 使用示例 <!-- non-responsive: --> <img data-src="image.jpg" class="lazyload" /> <!-- responsive example with automatic sizes calculation: --&g

javascript图片加载---加载大图的一个解决方案

网页在加载一张大图片时,往往要加载很久: 而且,在加载过程中,无法很好地控制图片的样式,容易造成错位等显示错误: 如果能够在加载大图时,先使用一张较小的loading图片占位,然后后台加载大图片,当大图片加载完成后,自动替换占位图, 这样能提供更好的用户体验: 由于,我在开发一个图片查看器时,遇到这样的需求,所以我写了个angular服务,来解决这个问题,效果还不错: 虽然是angular服务,当是把里面核心代码抽出来也可以单独使用: 来分享下源代码: 一: var imgloader = ne

imagepool前端图片加载管理器(JavaScript图片连接池)

前言 imagepool是一款管理图片加载的JS工具,通过imagepool可以控制图片并发加载个数. 对于图片加载,最原始的方式就是直接写个img标签,比如:<img src="图片url" />. 经过不断优化,出现了图片延迟加载方案,这回图片的URL不直接写在src属性中,而是写在某个属性中,比如:<img src="" data-src="图片url" />.这样浏览器就不会自动加载图片,等到一个恰当的时机需要加载

Android 图片加载框架Universal-Image-Loader源码解析

Universal-Image-Loader(项目地址)可以说是安卓知名图片开源框架中最古老.使用率最高的一个了.一张图片的加载对于安卓应用的开发也许是件简单的事,但是如果要同时加载大量的图片,并且图片用于ListView.GridView.ViewPager等控件,如何防止出现OOM.如何防止图片错位(因为列表的View复用功能).如何更快地加载.如何让客户端程序员用最简单的操作完成本来十分复杂的图片加载工作,成了全世界安卓应用开发程序员心头的一大难题,所幸有了Universal-Image-

jQuery Mobile 手动显示ajax加载器

在jquery mobile开发中,经常需要调用ajax方法,异步获取数据,如果异步获取数据方法由于网速等等的原因,会有一个反应时间,如果能在点击按钮后数据处理期间,给一个正在加载的提示,客户体验会更好一些. 先看两个方法,显示和关闭,方法来自于参考:http://blog.csdn.net/zht666/article/details/8563025 <script> //显示加载器 function showLoader() { //显示加载器.for jQuery Mobile 1.2.

Android中常见的图片加载框架

图片加载涉及到图片的缓存.图片的处理.图片的显示等.而随着市面上手机设备的硬件水平飞速发展,对图片的显示要求越来越高,稍微处理不好就会造成内存溢出等问题.很多软件厂家的通用做法就是借用第三方的框架进行图片加载. 开源框架的源码还是挺复杂的,但使用较为简单.大部分框架其实都差不多,配置稍微麻烦点,但是使用时一般只需要一行,显示方法一般会提供多个重载方法,支持不同需要.这样会减少很不必要的麻烦.同时,第三方框架的使用较为方便,这大大的减少了工作量.提高了开发效率.本文主要介绍四种常用的图片加载框架,

Universal-Image-Loader(UIL)图片加载框架使用简单介绍

这个也是最近项目中使用到的第三方图片加载框架,在这里也自己总结一下,简单的介绍一些使用的方式. UIL图片加载框架特点 简介: 项目地址:https://github.com/nostra13/Android-Universal-Image-Loader 异步加载图片或者加载大量图片经常会遇到图片错乱或者OOM等相关问题.UIL图片缓存,目前使用最广泛的图片缓存,支持主流图片缓存的绝大多数特性. 我们看下该图片加载的三级缓存原理 特点: 1.多线程下载图片,图片可以来源于网络,文件系统,项目文件