iText缓慢并抛出OutOfMemoryError

时间:2016-02-01 18:26:02

标签: java android performance out-of-memory itext

我正在使用itextg-5.5.4在我的Android应用程序中创建一个报告。创建报告包括填写现有pdf(封面页)上的一些字段,生成两个新的pdf(报告的两个部分),然后将创建的pdf附加到修改后的pdf。这没有问题。我已经成功地制作了所需的结果pdf。

每个报告只是一个包含100-300行,包含页眉和页脚的表格。

新任务是在每一行添加注释字段。我使用this作为参考。

生成报告所需的时间现在明显更长,最终会抛出OutOfMemoryError。此外,当它尝试创建新字段时,我可以看到GC不断运行。

这些是我收到的GC消息的单个实例。实际上有很多:

02-01 13:00:09.959: I/art(25619): Background sticky concurrent mark sweep GC freed 23578(976KB) AllocSpace objects, 0(0B) LOS objects, 5% free, 91MB/97MB, paused 9.704ms total 81.207ms
02-01 13:00:10.759: I/art(25619): Background partial concurrent mark sweep GC freed 415615(14MB) AllocSpace objects, 1(32KB) LOS objects, 15% free, 89MB/105MB, paused 9.521ms total 538.818ms

这是最终的错误:

02-01 13:45:40.182: E/art(28586): Throwing OutOfMemoryError "Failed to allocate a 28 byte allocation with 6 free bytes and 6B until OOM" (recursive case)

我在for循环之外创建单元格,并在循环数据时更新它们的内容。我在有问题的行上添加了一条评论,以明确错误发生的位置。

        for(Bundle data : fac_data)
        {   
            index++;                
            //Violations
            violationtotals[0] = violationtotals[0] + data.getInt("Violation Count");
            violationtotals[1] = violationtotals[1] + data.getInt("Uncorrected Violations");

            //Device Inspections
            //0=Total, 1=Tested, 2=Failed, 3=repaired
            int [] pvb  = new int[]{0,0,0,0};
            int [] dcva = new int[]{0,0,0,0};
            int [] rpd  = new int[]{0,0,0,0};

            pvb[0] = data.getInt("TOTAL PVB");
            pvb[1] = data.getInt("Tested PVB");
            pvb[2] = data.getInt("Failed PVB");
            pvb[3] = data.getInt("Repaired PVB");

            dcva[0] = data.getInt("TOTAL DCVA");
            dcva[1] = data.getInt("Tested DCVA");
            dcva[2] = data.getInt("Failed DCVA");
            dcva[3] = data.getInt("Repaired DCVA");

            rpd[0] = data.getInt("TOTAL RPD");
            rpd[1] = data.getInt("Tested RPD");
            rpd[2] = data.getInt("Failed RPD");
            rpd[3] = data.getInt("Repaired RPD");

            //Device Inspection Totals
            pvbtotals[0] = pvbtotals[0] + pvb[0];
            pvbtotals[1] = pvbtotals[1] + pvb[1];
            pvbtotals[2] = pvbtotals[2] + pvb[2];
            pvbtotals[3] = pvbtotals[3] + pvb[3];
            dcvatotals[0] = dcvatotals[0] + dcva[0];
            dcvatotals[1] = dcvatotals[1] + dcva[1];
            dcvatotals[2] = dcvatotals[2] + dcva[2];
            dcvatotals[3] = dcvatotals[3] + dcva[3];
            rpdtotals[0] = rpdtotals[0] + rpd[0];
            rpdtotals[1] = rpdtotals[1] + rpd[1];
            rpdtotals[2] = rpdtotals[2] + rpd[2];
            rpdtotals[3] = rpdtotals[3] + rpd[3];

            //Package results
            result.putIntArray(BundleKeys.report_violation_totals.toString(), violationtotals);
            result.putIntArray(BundleKeys.report_rpd_totals.toString(), rpdtotals);
            result.putIntArray(BundleKeys.report_dcva_totals.toString(), dcvatotals);
            result.putIntArray(BundleKeys.report_pvb_totals.toString(), pvbtotals);

            //Create Report PDF

            //Index
            indexCell.setPhrase(new Phrase(Integer.toString(index), smallFont));
            MainTable.addCell(indexCell);

            //Consumer Name and Address Cell
            cnadCell.setPhrase((new Phrase(data.getString("Facility Name") + "\n\n" + data.getString("Address Line 1") + "\n" + data.getString("Address Line 2"), smallFont)));
            MainTable.addCell(cnadCell);

            //Categories of Concern Cell
            cocCell.setPhrase(new Phrase(data.getString("Concerns"), smallFont));
            MainTable.addCell(cocCell);

            //Date of Inspection Cell
            doiCell.setPhrase(new Phrase(data.getString("Inspection Date"), smallFont));
            MainTable.addCell(doiCell);

            //Violations Found Cell
            violationFoundCell.setPhrase(new Phrase(Integer.toString(data.getInt("Violation Count")), smallFont));
            MainTable.addCell(violationFoundCell);

            //Violations Uncorrected Cell
            violationUncorrectedCell.setPhrase(new Phrase(Integer.toString(data.getInt("Uncorrected Violations")), smallFont));
            MainTable.addCell(violationUncorrectedCell);

            //Handle nulls
            String vstatus = data.getString("Violation Status");
            if(vstatus == null)
            {
                vstatus = "";
            }//if

            //Violation Status Cell
            violationStatusCell.setPhrase(new Phrase(data.getString(vstatus), smallFont));
            MainTable.addCell(violationStatusCell);

            //PVB device cells
            MainTable.addCell(pvbLabel);
            for(int i : pvb)
            {
                deviceValueCell.setPhrase(new Phrase(Integer.toString(i), smallFont));
                MainTable.addCell(deviceValueCell);
            }//for

            //THIS IS THE NEW LINE
            String commentName = annual ? "annual" : "quintennail";
            inspectionCommentsLine.setCellEvent(new CommentField(commentName + Integer.toString(index)));
            MainTable.addCell(inspectionCommentsLine);

            //DCVA device cells
            MainTable.addCell(dcvaLabel);
            for(int i : dcva)
            {
                deviceValueCell.setPhrase(new Phrase(Integer.toString(i), smallFont));
                MainTable.addCell(deviceValueCell);
            }//for  

            //RPD Device Cells
            MainTable.addCell(rpdLabel);
            for(int i : rpd)
            {
                deviceValueCell.setPhrase(new Phrase(Integer.toString(i), smallFont));
                deviceValueCell.setBorderWidthBottom(1.5f);
                MainTable.addCell(deviceValueCell);
            }//for
        }//for

然后将MainTable添加到文档中。

这就是我自定义单元格事件的位置:

private class CommentField implements PdfPCellEvent 
{
    protected String fieldname;
    public CommentField(String fieldname) 
    {
        this.fieldname = fieldname;
    }//Constructor
    public void cellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases) 
    {
        final PdfWriter writer = canvases[0].getPdfWriter();
        final TextField textField = new TextField(writer, rectangle, fieldname);
        try 
        {
            //THIS IS WHERE THE OutOfMemoryError POINTS TO IN STACK TRACE 
            final PdfFormField field = textField.getTextField();
            writer.addAnnotation(field);
        }//try
        catch (final IOException ioe) 
        {
            throw new ExceptionConverter(ioe);
        }//catch
        catch (final DocumentException de) 
        {
            throw new ExceptionConverter(de);
        }//catch
    }//cellLayout
}//CommentField

我做错了吗?在pdf中有几百个字段是不是很糟糕?

0 个答案:

没有答案