ListView To Bitmap

公司有需求,需要将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();


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值