David PHAM-VAN

Improve PdfPreview memory consumption

@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 4
5 - iOS: Set cutLength to be currentSize.height [Liam Downey] 5 - iOS: Set cutLength to be currentSize.height [Liam Downey]
6 - Add Flutter 3 warning workaround 6 - Add Flutter 3 warning workaround
  7 +- Improve PdfPreview memory consumption
7 8
8 ## 5.9.0 9 ## 5.9.0
9 10
@@ -16,20 +16,24 @@ @@ -16,20 +16,24 @@
16 16
17 import 'package:flutter/material.dart'; 17 import 'package:flutter/material.dart';
18 18
19 -import '../raster.dart';  
20 -  
21 /// Represents one PDF page 19 /// Represents one PDF page
22 class PdfPreviewPage extends StatelessWidget { 20 class PdfPreviewPage extends StatelessWidget {
23 /// Create a PDF page widget 21 /// Create a PDF page widget
24 const PdfPreviewPage({ 22 const PdfPreviewPage({
25 Key? key, 23 Key? key,
26 - this.page, 24 + required this.image,
  25 + required this.width,
  26 + required this.height,
27 this.pdfPreviewPageDecoration, 27 this.pdfPreviewPageDecoration,
28 this.pageMargin, 28 this.pageMargin,
29 }) : super(key: key); 29 }) : super(key: key);
30 30
31 /// Image representing the content of the page 31 /// Image representing the content of the page
32 - final PdfRaster? page; 32 + final ImageProvider image;
  33 +
  34 + final int width;
  35 +
  36 + final int height;
33 37
34 /// Decoration around the page 38 /// Decoration around the page
35 final Decoration? pdfPreviewPageDecoration; 39 final Decoration? pdfPreviewPageDecoration;
@@ -39,7 +43,6 @@ class PdfPreviewPage extends StatelessWidget { @@ -39,7 +43,6 @@ class PdfPreviewPage extends StatelessWidget {
39 43
40 @override 44 @override
41 Widget build(BuildContext context) { 45 Widget build(BuildContext context) {
42 - final im = PdfRasterImage(page!);  
43 final scrollbarTrack = Theme.of(context) 46 final scrollbarTrack = Theme.of(context)
44 .scrollbarTheme 47 .scrollbarTheme
45 .thickness 48 .thickness
@@ -66,9 +69,9 @@ class PdfPreviewPage extends StatelessWidget { @@ -66,9 +69,9 @@ class PdfPreviewPage extends StatelessWidget {
66 ], 69 ],
67 ), 70 ),
68 child: AspectRatio( 71 child: AspectRatio(
69 - aspectRatio: page!.width / page!.height, 72 + aspectRatio: width / height,
70 child: Image( 73 child: Image(
71 - image: im, 74 + image: image,
72 fit: BoxFit.cover, 75 fit: BoxFit.cover,
73 ), 76 ),
74 ), 77 ),
@@ -183,8 +183,8 @@ class _PdfPreviewState extends State<PdfPreview> { @@ -183,8 +183,8 @@ class _PdfPreviewState extends State<PdfPreview> {
183 183
184 if (!widget.canChangePageFormat && pages.isNotEmpty) { 184 if (!widget.canChangePageFormat && pages.isNotEmpty) {
185 format = PdfPageFormat( 185 format = PdfPageFormat(
186 - pages.first.page!.width * PdfPageFormat.inch / dpi,  
187 - pages.first.page!.height * PdfPageFormat.inch / dpi, 186 + pages.first.width * PdfPageFormat.inch / dpi,
  187 + pages.first.height * PdfPageFormat.inch / dpi,
188 marginAll: 5 * PdfPageFormat.mm, 188 marginAll: 5 * PdfPageFormat.mm,
189 ); 189 );
190 } 190 }
@@ -37,7 +37,7 @@ mixin PdfPreviewRaster on State<PdfPreviewCustom> { @@ -37,7 +37,7 @@ mixin PdfPreviewRaster on State<PdfPreviewCustom> {
37 PdfPageFormat get pageFormat => widget.pageFormat; 37 PdfPageFormat get pageFormat => widget.pageFormat;
38 38
39 /// Resulting pages 39 /// Resulting pages
40 - final List<PdfPreviewPage> pages = <PdfPreviewPage>[]; 40 + final pages = <PdfPreviewPage>[];
41 41
42 /// Printing subsystem information 42 /// Printing subsystem information
43 PrintingInfo? info; 43 PrintingInfo? info;
@@ -57,6 +57,10 @@ mixin PdfPreviewRaster on State<PdfPreviewCustom> { @@ -57,6 +57,10 @@ mixin PdfPreviewRaster on State<PdfPreviewCustom> {
57 @override 57 @override
58 void dispose() { 58 void dispose() {
59 _previewUpdate?.cancel(); 59 _previewUpdate?.cancel();
  60 + for (final e in pages) {
  61 + e.image.evict();
  62 + }
  63 + pages.clear();
60 super.dispose(); 64 super.dispose();
61 } 65 }
62 66
@@ -159,26 +163,35 @@ mixin PdfPreviewRaster on State<PdfPreviewCustom> { @@ -159,26 +163,35 @@ mixin PdfPreviewRaster on State<PdfPreviewCustom> {
159 _rastering = false; 163 _rastering = false;
160 return; 164 return;
161 } 165 }
162 - setState(() {  
163 - if (pages.length <= pageNum) {  
164 - pages.add(PdfPreviewPage(  
165 - page: page,  
166 - pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,  
167 - pageMargin: widget.previewPageMargin,  
168 - ));  
169 - } else {  
170 - pages[pageNum] = PdfPreviewPage(  
171 - page: page,  
172 - pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,  
173 - pageMargin: widget.previewPageMargin,  
174 - );  
175 - }  
176 - }); 166 +
  167 + if (pages.length <= pageNum) {
  168 + pages.add(PdfPreviewPage(
  169 + image: MemoryImage(await page.toPng()),
  170 + width: page.width,
  171 + height: page.height,
  172 + pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,
  173 + pageMargin: widget.previewPageMargin,
  174 + ));
  175 + } else {
  176 + pages[pageNum].image.evict();
  177 + pages[pageNum] = PdfPreviewPage(
  178 + image: MemoryImage(await page.toPng()),
  179 + width: page.width,
  180 + height: page.height,
  181 + pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,
  182 + pageMargin: widget.previewPageMargin,
  183 + );
  184 + }
  185 + setState(() {});
177 186
178 pageNum++; 187 pageNum++;
179 } 188 }
180 189
  190 + for (var index = pageNum; index < pages.length; index++) {
  191 + pages[index].image.evict();
  192 + }
181 pages.removeRange(pageNum, pages.length); 193 pages.removeRange(pageNum, pages.length);
  194 + setState(() {});
182 } catch (exception, stack) { 195 } catch (exception, stack) {
183 InformationCollector? collector; 196 InformationCollector? collector;
184 197