normal:https://picgo-1253786286.cos.ap-guangzhou.myqcloud.com/image/1604672692.mp4
lag:https://picgo-1253786286.cos.ap-guangzhou.myqcloud.com/image/1604672768.mp4
This is original html string:https://picgo-1253786286.cos.ap-guangzhou.myqcloud.com/image/1604672863.dart
``` dart
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Padding(
padding: EdgeInsets.fromLTRB(20, 30, 20, 30),
child: HtmlWidget(
html,
customStylesBuilder: (element) {
if (element.localName.contains('p')) {
return {
'white-space': 'normal',
// 'text-align': 'justify',
'word-break': 'break-all',
};
} else if (element.localName.contains('blockquote')) {
return {
'background-color': 'rgba(0, 0, 0, 0.04)',
'margin': '0',
'padding': '0.5em 0.5em'
};
} else if (element.localName.contains('ul')) {
return {'padding': '0 0 0 25px'};
} else if (element.localName.contains('li')) {
return {'margin-bottom': '10px'};
}
return null;
},
onTapUrl: (url) => this._launchURL(url),
textStyle: TextStyle(fontSize: 16, height: 1.6),
),
))
The HTML is huge, we have too many widgets at once and they are all rendered together so maybe that's why it's slow. I'll see what can be done.
Currently we're using flutter_html, but your library looks promising and seems to have a better performance on large html documents :) (I also loved your XenForo plugin for the attachment store). How did you manage that the performance of many widgets here is much better? Especially on weaker Android devices it stutters a lot more with flutter_html. Sometimes it's also here a bit laggy for example when the content is placed inside of PageView and when swiping to the next entry, but it's seems to be better then with flutter_html.
With flutter_html we're using a ListView to show the HTML content as described here, but there are some drawbacks. For example anchor links are difficult to handle.
Thanks for the kind word @DFelten. There are a few things maybe:
Thanks for the explanation :) The async feature is also really good, but only when using just one HtmlWidget and not multiple in a ListView. Within a ListView the performance of large documents is better, but that's of course not working for all html structures.
We currently process the HTML content in this way. Perhaps this is a starting point to generally improve the performance for large HTML documents. An idea would be a separate HtmlWidgetList.
List<String> splitHtmlContent() {
final List<String> stringList = [];
for (final Element element in document.body.children) {
stringList.add(element.outerHtml);
}
return stringList;
}
With this String list it's possible to ad the html content into a List or SliverList like this:
Widget build(BuildContext context) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => HtmlWidget(htmlStrings[index]),
childCount: htmlStrings.length,
),
);
}
As mentioned above, the Anchor Links cause problems. Therefore we save them together with the exact position in a map. So they work again.
@DFelten just an update on this: I have just tried a simple diff:
diff --git a/packages/core/lib/src/core_widget_factory.dart b/packages/core/lib/src/core_widget_factory.dart
index 9e34999..a18fbb6 100644
--- a/packages/core/lib/src/core_widget_factory.dart
+++ b/packages/core/lib/src/core_widget_factory.dart
@@ -49,9 +49,13 @@ class WidgetFactory {
AspectRatio(aspectRatio: aspectRatio, child: child);
/// Builds primary column (body).
- WidgetPlaceholder? buildBody(
- BuildMetadata meta, Iterable<WidgetPlaceholder> children) =>
- buildColumnPlaceholder(meta, children, trimMarginVertical: true);
+ Widget? buildBody(BuildMetadata meta, Iterable<WidgetPlaceholder> children) {
+ final list = children.toList(growable: false);
+ return ListView.builder(
+ itemBuilder: (_, i) => list[i],
+ itemCount: list.length,
+ );
+ }
Instead of a big column containing all the children widgets, this diff will use a single ListView at the top level. The change is minimal but the performance gain is quite significant. With a 200KB html input, the first frame (the laggiest) went from 1000ms down to 31ms, only twice the 17ms target for smooth 60fps rendering.
| Before | After |
| --- | --- |
|
|
|
@daohoangson Can HTML code like below benefit on this improvment?
<div>
<div>
<div>
<div>
<p>abcd</p>
...<!-- very long long HTML codes -->
</div>
</div>
</div>
</div>
Thanks!
@Doflatango not yet because the big DIV will be render all at once by the SliverList. I'm working on this though, you can follow the progress at #484
@Doflatango not yet because the big DIV will be render all at once by the
SliverList. I'm working on this though, you can follow the progress at #484
Thanks!
Most helpful comment
Thanks for the kind word @DFelten. There are a few things maybe: