Android-ListView 内存、硬盘缓存复用
本文最后更新于 91 天前,其中的信息可能已经有所发展或是发生改变。

getView内通过parent来获取ListView/GridView findViewWithTag方法去获取对应的ImageView(ImageView设置tag)

public class GmGalleryGridAdapter extends BaseAdapter {
    private Context context;
    private List<GmLocalMedia> data;
    private final ExecutorService executorService;
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // CPU 核心数
    private static final int THREAD_POOL_SIZE = Math.min(CPU_COUNT * 2, 4); // 线程池大小
    private final ArrayList<Future<?>> activeTasks = new ArrayList<>();
    private LruCache<String, Bitmap> mBitmapCache;  // 使用 LruCache 来缓存图片

    private OnSelectGalleryListener selectGalleryListener;
    public GmGalleryGridAdapter(Context context, List<GmLocalMedia> data,OnSelectGalleryListener onSelectGalleryListener) {
        this.context = context;
        this.data = data;
        this.selectGalleryListener = onSelectGalleryListener;

        // 初始化线程池
        executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

        // 初始化 LruCache
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // 获取最大内存
        final int cacheSize = maxMemory / 8; // 设置缓存大小为最大内存的 1/8
        mBitmapCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount() / 1024; // 返回图片的内存占用
            }
        };
    }

    @Override
    public int getCount() {
        return data.size();
    }

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

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

    private GridView mGridView;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (mGridView == null) {
            mGridView = (GridView) parent;
        }
        GmLocalMedia media = data.get(position);
        String path = media.getPath();
        String fileName = media.getFileName();
        View view;
        ViewHolder viewHolder;

        if (convertView == null) {
            view = Ext.getLayoutView("gamehelper_gallery_item");
            viewHolder = new ViewHolder();
            viewHolder.img = (ImageView) Ext.getWidgetView(view,"gamehelper_gallery_item_img");
            view.setTag(viewHolder);
        } else {
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }
        Uri uri = GmMediaUtils.isContent(path) ? Uri.parse(path) : Uri.fromFile(new File(path));

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("dqs",">>>>>>>>>>>>>> 选择的图片文件大小 " + media.getSize());
                if(media.getSize() > 20 * 1024 * 1024) {
                    Ext.toast("请选择小于20M的图片", Toast.LENGTH_SHORT);
                    return;
                }
                if(selectGalleryListener != null) {
                    selectGalleryListener.onSelectGallery(uri,fileName);
                }
            }
        });

        viewHolder.img.setTag(uri);
        viewHolder.img.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), Ext.getDrawableId("gamehelper_image_placeholder")));


        // 检查缓存,若存在则直接加载缓存图片
        Bitmap bitmap = mBitmapCache.get(uri.toString());
        if (bitmap != null) {
            viewHolder.img.setImageBitmap(bitmap);
        } else {
            loadImageAsync(uri, viewHolder, position); // 图片缓存中没有,异步加载
        }
        return view;
    }

    private Handler mHandler = new Handler(Looper.getMainLooper());


    // 用来跟踪每个图片加载任务

    private void loadImageAsync(Uri uri, ViewHolder viewHolder, int position) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = loadImage(uri); // 从磁盘或网络加载图片
                mBitmapCache.put(uri.toString(), bitmap); // 缓存图片
                if (bitmap != null) {
                    // 在主线程更新 UI
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            ImageView view = mGridView.findViewWithTag(uri);
                            if (view != null) {
                                view.setImageBitmap(bitmap);
                            }
                        }
                    });
                }
            }
        };
        executorService.submit(runnable);
    }

    private Bitmap loadImage(Uri uri) {
        try {
            // 判断 URI 是否是 file:// 开头
            if (uri != null) {
                try {
                    InputStream inputStream = context.getContentResolver().openInputStream(uri);
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    BitmapFactory.decodeStream(inputStream, null, options);

                    // 计算适当的采样率
                    options.inSampleSize = calculateInSampleSize(options, 80, 80); // 根据需求调整目标宽高
                    options.inJustDecodeBounds = false;

                    // 重新打开输入流并加载图片
                    InputStream inputStreamForBitmap = context.getContentResolver().openInputStream(uri);
                    return BitmapFactory.decodeStream(inputStreamForBitmap, null, options);
                } catch (Exception e) {
                    Log.d("dqs", ">>>>>> " + uri + "<>" + e.getMessage());
                }
            }
        } catch (Exception e) {
            Log.d("dqs", "Error decoding image", e);
        }
        return null;
    }

    private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        int height = options.outHeight;
        int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

    static class ViewHolder {
        ImageView img;
    }
}
本文链接:https://iichen.cn/?p=825
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇