仿微信选择图片之——加载内存中所有图片

本文详细介绍了如何使用 LruCache 实现内存缓存优化,结合 ContentResolvePic 类获取硬盘中的图片信息,并通过 NativeImageLoader 类进行图片缓存与加载。文章进一步封装了 ImageUtil 类用于图片的放大或缩小,合理利用内存资源。最后,通过 GalleryAdapter 类实现了图片的适配器和显示功能,包括滑动时的图片加载控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文采用了结合LruCache内存缓存方式,LruCache介绍请看:http://blog.youkuaiyun.com/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;
    }
}


基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。 智能教学辅助系统 这是一个智能教学辅助系统的前端项目,基于 Vue3+TypeScript 开发,使用 Ant Design Vue 作为 UI 组件库。 功能模块 用户模块 登录/注册功能,支持学生和教师角色 毛玻璃效果的登录界面 教师模块 备课与设计:根据课程大纲自动设计教学内容 考核内容生成:自动生成多样化考核题目及参考答案 学情数据分析:自动化检测学生答案,提供数据分析 学生模块 在线学习助手:结合教学内容解答问题 实时练习评测助手:生成随练题目并纠错 管理模块 用户管理:管理员/教师/学生等用户基本管理 课件资源管理:按学科列表管理教师备课资源 大屏概览:使用统计、效率指数、学习效果等 技术栈 Vue3 TypeScript Pinia 状态管理 Ant Design Vue 组件库 Axios 请求库 ByteMD 编辑器 ECharts 图表库 Monaco 编辑器 双主题支持(专业科技风/暗黑风) 开发指南 # 安装依赖 npm install # 启动开发服务器 npm run dev # 构建生产版本 npm run build 简介 本项目旨在开发一个基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值