ListView To Bitmap

介绍了一种方法,用于将Android中的ListView转换为一系列图片,通过分页处理避免内存溢出,并提供了详细的实现代码。

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

公司有需求,需要将listview的全部内容生成一组图片,于是有了以下代码

public class ListViewToBitmap {

    private ListView mListView;

    private ListAdapter mAdapter;

    private int childCount;

    // 每页的项目数, 默认情况下,只是一页,但是极有可能导致oom异常
    private int countPerPage = Integer.MAX_VALUE;

    // 默认情况下,只是保存在文件中,不保存在内存中
    private boolean inMemory = false;

    private InMemoryCallBack inMemoryCallBack;

    private boolean inFile = true;

    private InFileCallBack inFileCallBack;

    private Handler uiThreadHandler;

    private static final int MEMORY_HANDLED = 1;
    private static final int FILE_HANDLED = 2;

    private List<Bitmap> memoryDatas = new ArrayList<>();

    private List<String> filePaths = new ArrayList<>();

    // 图片文件目录
    private File filesDir;

    private ListViewToBitmap(ListView listView) {

        this(listView, Integer.MAX_VALUE);
    }

    private ListViewToBitmap(ListView listView, int count_per_page) {

        mListView = listView;
        mAdapter = mListView.getAdapter();
        childCount = mAdapter.getCount();
        countPerPage = count_per_page;

        Context context = listView.getContext();
        filesDir = context.getExternalCacheDir();

        if (filesDir == null) {
            filesDir = context.getCacheDir();
        }
    }

    protected void setInMemory(InMemoryCallBack callBack) {
        inMemory = true;
        inMemoryCallBack = callBack;
    }

    protected void setInFile(InFileCallBack callBack) {
        inFile = true;
        inFileCallBack = callBack;
    }

    public void start() {

        if (uiThreadHandler == null) {

            uiThreadHandler = new Handler(Looper.getMainLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case MEMORY_HANDLED:{
                            if (inMemory && inMemoryCallBack!= null) {
                                inMemoryCallBack.onSuccess(memoryDatas);
                            }
                            break;
                        }
                        case FILE_HANDLED:{
                            if (inFile && inFileCallBack != null) {
                                inFileCallBack.onSuccess(filePaths);
                            }
                            break;
                        }
                    }
                }
            };
        }

        new Thread() {
            @Override
            public void run() {

                // 计算有多少页
                int page = childCount / countPerPage;

                if (childCount % countPerPage > 0) {

                    page += 1;
                }

                for (int pageIndex = 0; pageIndex < page; ++pageIndex) {

                    Bitmap bitmap = getBitmap(pageIndex);

                    if (inFile) {
                        String filepath = bitmapToFile(bitmap);
                        filePaths.add(filepath);
                    }

                    // 需要保存在内存中(非常容易出现oom)
                    if (inMemory) {
                        memoryDatas.add(bitmap);
                    } else {

                        // 及时清理内存才是正途
                        bitmap.recycle();
                    }
                }

                if (inFile) {

                    uiThreadHandler.sendEmptyMessage(FILE_HANDLED);
                }

                if (inMemory) {

                    uiThreadHandler.sendEmptyMessage(MEMORY_HANDLED);
                }
            }
        }.start();

    }

    private String bitmapToFile(Bitmap bitmap) {

        try {
            File file = getFile();
            file.createNewFile();
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 30, bos);
            bos.flush();
            bos.close();

            return file.getAbsolutePath();

        } catch (Exception e) {
            e.printStackTrace();

            return null;
        }
    }


    private File getFile() {
        File file = new File(filesDir, System.currentTimeMillis() + ".jpg");
        if (file.exists()) {
            return getFile();
        }
        else {
            return file;
        }
    }


    /**
     * 获取每一页的bitmap
     * @param page
     * @return
     */
    private Bitmap getBitmap(int page) {

        int pageStart = page * countPerPage;

        int pageEnd = pageStart + countPerPage > childCount ? childCount : pageStart + countPerPage;

        View child;
        int everyChildWidthMeasureSpec = View.MeasureSpec.makeMeasureSpec(mListView.getWidth(), View.MeasureSpec.EXACTLY);
        int childHeightMeasureSpec;
        int itemsHeight = 0;

        List<Bitmap> itemBitmaps = new ArrayList<>();

        // 获取到一页中,每个item的bitmap
        for (int i = pageStart; i < pageEnd; ++i) {
            child = mAdapter.getView(i, null, mListView);
            childHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);

            child.measure(everyChildWidthMeasureSpec, childHeightMeasureSpec);

            child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());

            child.setDrawingCacheEnabled(true);

            child.buildDrawingCache();

            itemBitmaps.add(child.getDrawingCache());

            itemsHeight += child.getMeasuredHeight();
        }

        // 创建一个大的空白的bitmap, 用来保存一页的内容
        Bitmap pageBitmap = Bitmap.createBitmap(mListView.getWidth(), itemsHeight, Bitmap.Config.RGB_565);

        Canvas pageCanvas = new Canvas(pageBitmap);

        Paint pagePaint = new Paint();

        int x = 0;
        int y = 0;

        Bitmap bitmap;

        // 逐步将一页的内容画进大的bitmap中
        for (int i = 0; i < itemBitmaps.size(); ++i) {

            bitmap = itemBitmaps.get(i);
            pageCanvas.drawBitmap(bitmap, x, y, pagePaint);

            y += bitmap.getHeight();

            // 及时回收每一个item的内存
            bitmap.recycle();
        }

        return pageBitmap;
    }



    public static class Builder {

        private ListView listView;

        private int count_per_page = Integer.MAX_VALUE;

        private boolean inMemory;

        private boolean inFile;

        private InMemoryCallBack inMemoryCallBack;

        private InFileCallBack inFileCallBack;

        public Builder(ListView list) {
            listView = list;
        }

        public Builder countPerPage(int cpp) {

            count_per_page = cpp;
            return this;
        }

        public Builder inMemory(InMemoryCallBack callBack) {

            inMemory = true;
            inMemoryCallBack = callBack;
            return this;
        }

        public Builder inFile(InFileCallBack callBack) {

            inFile = true;
            inFileCallBack = callBack;
            return  this;
        }

        public ListViewToBitmap build() {

            ListViewToBitmap listViewToBitmap = new ListViewToBitmap(listView, count_per_page);

            if (inMemory) {
                listViewToBitmap.setInMemory(inMemoryCallBack);
            }

            if (inFile) {
                listViewToBitmap.setInFile(inFileCallBack);
            }

            return listViewToBitmap;
        }
    }

    public interface InMemoryCallBack {

        void onSuccess(List<Bitmap> bitmaps);
    }

    public interface InFileCallBack {

        void onSuccess(List<String> filePaths);
    }
}


主要目的是在工作线程里面执行分页操作,及时释放内存,避免oom


使用方法:

ListViewToBitmap listViewToBitmap = new ListViewToBitmap.Builder(lv)
                .countPerPage(30)
                .inFile(inFileCallBack)
                .build();

   
        listViewToBitmap.start();


资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值