ListView To Bitmap

来源:互联网 发布:caffe怎么用model 编辑:程序博客网 时间:2024/05/22 14:40

公司有需求,需要将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
原创粉丝点击