Infinite ListView of Images freeze app or throw exceptions during layout [small app included]
Hm... Docs say:
/// 2. The [ListView.builder] constructor takes an [IndexedWidgetBuilder], which
/// builds the children on demand. This constructor is appropriate for list views
/// with a large (or infinite) number of children because the builder is called
/// only for those children that are actually visible.
Which, in theory, should make it possible what you want to do. For whatever reason, you seem to run into a loop. itemBuilder
keep getting invoked. My guess is that until the assets is loaded and actually rendered, it's dimensions can't be determined.
You can verify this by setting an itemCount: 1
and see the freeze gone. Also, setting an initial contraint on the width of the Image
helps:
return ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
return ConstrainedBox(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
maxWidth: double.infinity,
),
child: Image.asset(
'assets/repeatable-forest.jpg',
fit: BoxFit.fitHeight,
),
);
},
);
If anyone could provide some insight into why exactly itemBuilder
keeps getting invoked, that's be awesome.
Joel Broström
Updated on December 02, 2022Comments
-
Joel Broström over 1 year
I'm trying to make a horizontally scrolling ListView with repeatable images to make it seem like it's one long image scrolling forever (like in 2d platform game).
However, when I add images to the ListView.build(...) method I can't get them to scale properly. I want the Images to
.fitHeight
and after trying all widgets I can think of I get one of two outcomes.- The app boots but freezes
- The app runs but throws exceptions
Here is the code in its entirety:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home: Scaffold( body: MyHomePage(), ), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { /// Freezes app and prevents it from hot reload/rebuild until app is manually terminated. Widget image = Image.asset('assets/repeatable-forest.jpg', fit: BoxFit.fitHeight); /// Wrapping Image in a FittedBox works, but with a lot of exceptions/warnings Widget fittedWrappedImage = FittedBox(child: Image.asset('assets/repeatable-forest.jpg'), fit: BoxFit.fitHeight); return ListView.builder( scrollDirection: Axis.horizontal, controller: ScrollController(), itemBuilder: (BuildContext context, int index) { return image; //fittedWrappedImage; <-- choose which one to test. }, ); } }
If you want to try it out with the example image (actually looks pretty good) you can download the "entire" repo here: https://github.com/joelbrostrom/infinite_listview_image_freeze_example
As you can see in the code comments
Image.asset()
freeze the app and wrapping it aFittedBox
makes it runnable but with exceptions.In my main project the second approach builds with exceptions in debug congif, but freezes in release. Maybe that's a clue?
Here is the exception I get when wrapping the image in the
FittedBox
:I/flutter (27099): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════ I/flutter (27099): The following assertion was thrown during performLayout(): I/flutter (27099): 'package:flutter/src/rendering/box.dart': Failed assertion: line 307 pos 12: 'width > 0.0': is not I/flutter (27099): true. I/flutter (27099): I/flutter (27099): Either the assertion indicates an error in the framework itself, or we should provide substantially I/flutter (27099): more information in this error message to help you determine and fix the underlying cause. I/flutter (27099): In either case, please report this assertion by filing a bug on GitHub: I/flutter (27099): https://github.com/flutter/flutter/issues/new?template=BUG.md I/flutter (27099): I/flutter (27099): When the exception was thrown, this was the stack: I/flutter (27099): #2 BoxConstraints.constrainSizeAndAttemptToPreserveAspectRatio (package:flutter/src/rendering/box.dart:307:12) I/flutter (27099): #3 RenderFittedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:2288:26) I/flutter (27099): #4 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #5 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #6 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #7 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #8 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #9 RenderSliverList.performLayout (package:flutter/src/rendering/sliver_list.dart:164:27) I/flutter (27099): #10 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #11 RenderSliverPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:182:11) I/flutter (27099): #12 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #13 RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:407:13) I/flutter (27099): #14 RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1322:12) I/flutter (27099): #15 RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1240:20) I/flutter (27099): #16 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #17 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #18 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #19 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #20 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #21 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #22 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #23 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #24 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #25 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #26 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #27 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #28 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #29 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #30 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #31 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #32 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #33 MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:142:11) I/flutter (27099): #34 _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:350:7) I/flutter (27099): #35 MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:212:7) I/flutter (27099): #36 RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:356:14) I/flutter (27099): #37 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #38 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #39 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #40 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #41 _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1206:11) I/flutter (27099): #42 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #43 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #44 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #45 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #46 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #47 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #48 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #49 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #50 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #51 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #52 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #53 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #54 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #55 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #56 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #57 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #58 RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3032:13) I/flutter (27099): #59 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #60 RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15) I/flutter (27099): #61 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #62 __RenderTheatre&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #63 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #64 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #65 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #66 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #67 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #68 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #69 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #70 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #71 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #72 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13) I/flutter (27099): #73 RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7) I/flutter (27099): #74 RenderView.performLayout (package:flutter/src/rendering/view.dart:151:13) I/flutter (27099): #75 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1507:7) I/flutter (27099): #76 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:766:18) I/flutter (27099): #77 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:329:19) I/flutter (27099): #78 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13) I/flutter (27099): #79 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5) I/flutter (27099): #80 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15) I/flutter (27099): #81 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9) I/flutter (27099): #82 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:749:7) I/flutter (27099): #91 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19) I/flutter (27099): #92 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5) I/flutter (27099): #93 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12) I/flutter (27099): (elided 10 frames from class _AssertionError and package dart:async) I/flutter (27099): I/flutter (27099): The following RenderObject was being processed when the exception was fired: I/flutter (27099): RenderFittedBox#fc66f relayoutBoundary=up5 NEEDS-LAYOUT NEEDS-PAINT I/flutter (27099): creator: FittedBox ← RepaintBoundary-[<0>] ← IndexedSemantics ← I/flutter (27099): NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← SliverList ← I/flutter (27099): MediaQuery ← SliverPadding ← Viewport ← IgnorePointer-[GlobalKey#aa491] ← Semantics ← ⋯ I/flutter (27099): parentData: <none> (can use size) I/flutter (27099): constraints: BoxConstraints(0.0<=w<=Infinity, h=1089.8) I/flutter (27099): size: MISSING I/flutter (27099): fit: fitHeight I/flutter (27099): alignment: center I/flutter (27099): textDirection: ltr I/flutter (27099): This RenderObject had the following descendants (showing up to depth 5): I/flutter (27099): RenderSemanticsAnnotations#bfe63 relayoutBoundary=up6 NEEDS-PAINT I/flutter (27099): RenderImage#90dc8 relayoutBoundary=up7 NEEDS-PAINT I/flutter (27099): ════════════════════════════════════════════════════════════════════════════════════════════════════ I/flutter (27099): Another exception was thrown: RenderBox was not laid out: RenderFittedBox#fc66f relayoutBoundary=up5 NEEDS-PAINT I/flutter (27099): Another exception was thrown: RenderBox was not laid out: RenderRepaintBoundary#4ba38 relayoutBoundary=up4 NEEDS-PAINT I/flutter (27099): Another exception was thrown: 'package:flutter/src/rendering/sliver_multi_box_adaptor.dart': Failed assertion: line 467 pos 12: 'child.hasSize': is not true. I/flutter (27099): Another exception was thrown: NoSuchMethodError: The getter 'scrollOffsetCorrection' was called on null. I/flutter (27099): Another exception was thrown: NoSuchMethodError: The method 'debugAssertIsValid' was called on null. I/flutter (27099): Another exception was thrown: NoSuchMethodError: The getter 'visible' was called on null. I/flutter (27099): Another exception was thrown: NoSuchMethodError: The getter 'visible' was called on null. D/libGLESv2(27099): STS_GLApi : DTS, ODTC are not allowed for Package : com.example.listview_image_scaling_issue
Any insight would be appreciated!