fix(pdfviewer): skip page text extraction when enableTextSelection is false - #2560
Conversation
… false _checkVisiblePages() calls PdfTextExtractor.extractText() unconditionally for every visible page, regardless of the enableTextSelection property. The extraction runs synchronously on the UI isolate and its results are cached in _pageTextExtractor, which is only cleared when the document changes. On large documents this causes an unrecoverable "Out of Memory" in the Dart heap and an Android ANR, because the parse allocates growable byte lists per content stream while the cache keeps every previously visited page alive. Guard the three extractText() call sites with widget.enableTextSelection so applications that disable text selection do not pay for extraction they cannot use. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Hi @ali-pouneh , Thank you for sharing your proposal and providing the patch to an issue where unnecessary extractText() calls cause OOM and ANR on large PDFs. Please note that, although the Flutter PDF Viewer source code is publicly available on GitHub for transparency, we do not accept direct contributions to the repository. This policy ensures consistency and quality across all releases. Nevertheless, your feedback and suggestions are highly valued, and we encourage you to continue sharing ideas through our official support channels. sfpdfviewer_gh2560.mp4Regards, |
|
Hi @AbinayaSF4962, thanks for looking. Reproduction depends on document size and device memory, and a small sample won't show it. The underlying issue doesn't need a repro, though: We've already shipped our app with this patch applied via a path override, and it resolved the OOM and ANR for us. So we're unblocked. I'm raising it here because other users setting Two things I'd appreciate a direct answer on:
|
|
Hi @ali-pouneh , Please find the details below,
Regards, |
Summary
SfPdfViewerState._checkVisiblePages()callsPdfTextExtractor.extractText()for every visible page unconditionally — theenableTextSelectionproperty is never consulted. On large documents this produces an unrecoverable DartOut of Memoryand an Android ANR.This PR guards the three
extractText()call sites withwidget.enableTextSelection.The problem
In
lib/src/pdfviewer.dart,enableTextSelectionis referenced in exactly one place (line 3786), where it is forwarded to the page widget for the selection UI. It does not gate extraction. Meanwhile_checkVisiblePages()extracts text at three sites (single-page mode, and the forward/backward visible-page loops), and the results are cached in_pageTextExtractor, which is cleared only when the document changes — so every page visited during a session stays resident.Extraction runs synchronously on the UI isolate. The combination means an application that sets
enableTextSelection: falsestill pays the full parse cost, and on a large document the allocation eventually fails.Reproduction
Android release build, Pixel 9 / Android 17,
syncfusion_flutter_pdfviewer33.2.7, ~50-page PDF,PdfPageLayoutMode.continuous,enableTextSelection: false. Paging through the document withPdfViewerController.nextPage()reliably reproduces it.Followed by:
Note frames #20–#26: the extraction is reached from the UI isolate via a tap handler, which is what turns the memory problem into an ANR.
Measured effect
adb shell dumpsys meminfo, same device, same document, same navigation, release builds:Unknown(Dart/native)Out of MemoryoccurrencesPage rendering is also visibly faster, since the UI isolate no longer parses content streams for every page that scrolls into view.
Scope and compatibility
enableTextSelectiondefaults totrue, so existing behaviour is unchanged for applications that do not opt out. Only applications that explicitly setenableTextSelection: falseare affected, and for those the extracted text was already unusable for selection.One thing worth a maintainer's eye: if
_pageTextExtractoris consumed by any path other than selection when the flag is off, that path would now see an empty cache. I could not find one, but I do not know the codebase as well as you do.Separately, and not addressed here:
_pageTextExtractorhas no eviction policy while a document is open, so even withenableTextSelection: truememory grows with the number of pages visited. A bounded cache would likely help large documents independently of this change.Verification
Verified on a patched local copy of 33.2.7 consumed through a
dependency_overridespath override, in a release build on a physical device. The same three call sites are present and unguarded in 34.1.29 (this branch) and in the published 34.2.8.