J'ai créé une vue de liste avec des images de réseau et lorsque j'essaie de faire défiler la vue de liste, le défilement n'est pas fluide, c'est comme une secousse. Pour la mise en cache, j'ai utilisé cached_network_image: any, cette bibliothèque elle-même fonctionne très bien mais listview ne fait pas défiler correctement.
Je sais que nous pouvons y parvenir avec le widget Future, mais je ne sais pas comment renvoyer une image en cache avec le futur.
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
void main() {
runApp(
MaterialApp(
title: 'List view with network images',
home: ListViewController(),
)
);
}
class ListViewController extends StatelessWidget {
var imagesArray = [
"http://iastro.shangcarts.com/pub/media/notice/File-1550484786.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550218043.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550217808.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550111913.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550108862.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550024618.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550022739.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549935759.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549935073.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549850545.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549849978.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549008412.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548985261.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548821873.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548731040.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548641672.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548410089.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547774905.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547701178.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547625318.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547624883.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547619153.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547606341.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547606200.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547603338.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547602464.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547454842.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547192524.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547191374.jpg"
];
Widget _imageCell(String imageUrl) {
return ListTile(
leading: CachedNetworkImage(imageUrl: imageUrl, placeholder: CircularProgressIndicator(), errorWidget: Icon(Icons.error),),
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Material(
child: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return _imageCell(imagesArray[index]);
},
separatorBuilder: (context, index) => Divider(
color: Colors.black,
),
itemCount: imagesArray.length),
);
}
}
Modifier: Après avoir changé la configuration de la construction en Release toujours la même, saccadé .
3 Réponses :
Je ne pense pas qu'il existe une bonne solution pour le moment autre que de réduire la taille de l'image source. J'ai jeté un œil à votre liste d'images et certaines sont assez énormes.
https: / /github.com/renefloor/flutter_cached_network_image/issues/90
https: / /github.com/pejalo/flutter_image_performance
https: / /github.com/flutter/flutter/issues/25469
https://github.com/flutter/flutter/issues/27625#issuecomment-461677587
https://github.com/flutter/flutter/issues/2848
https://github.com/flutter/flutter/issues/2 6194
La réduction d'échelle du flottement est assez lente. L'équipe Flutter doit l'optimiser pour les performances.
Autre chose, votre code ne fonctionne pas sur Flutter stable
Flutter 1.0.0 ⢠channel stable ⢠https://github.com/flutter/flutter.git
Framework ⢠revision 5391447fae (3 months ago) ⢠2018-11-29 19:41:26 -0800
Engine ⢠revision 7375a0f414
Tools ⢠Dart 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)
Compiler message:
lib/main.dart:56:64: Error: The argument type '#lib1::CircularProgressIndicator'
can't be assigned to the parameter type '(#lib2::BuildContext, dart.core::String)
â #lib2::Widget'.
Try changing the type of the parameter, or casting the argument to
'(#lib2::BuildContext, dart.core::String) â #lib2::Widget'.
leading: CachedNetworkImage(imageUrl: imageUrl, placeholder:
CircularProgressIndicator(), errorWidget: Icon(Icons.error),),
^
lib/main.dart:56:106: Error: The argument type '#lib1::Icon' can't be assigned to
the parameter type '(#lib2::BuildContext, dart.core::String, dart.core::Exception)
â #lib2::Widget'.
Try changing the type of the parameter, or casting the argument to
'(#lib2::BuildContext, dart.core::String, dart.core::Exception) â #lib2::Widget'.
leading: CachedNetworkImage(imageUrl: imageUrl, placeholder:
CircularProgressIndicator(), errorWidget: Icon(Icons.error),),
^
Compiler failed on /Users/blah/stackoverflow/issue_54786567/lib/main.dart
Error launching application on iPhone XR.
flutter run
Launching lib/main.dart on iPhone XR in debug mode...
Starting Xcode build...
ââAssembling Flutter resources... 3.9s
ââCompiling, linking and signing... 3.4s
Xcode build done. 9.1s
5.8s
Syncing files to device iPhone XR...
flutter: âââ¡ EXCEPTION CAUGHT BY RENDERING LIBRARY ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
flutter: The following assertion was thrown during performLayout():
flutter: BoxConstraints forces an infinite height.
flutter: These invalid constraints were provided to RenderSemanticsAnnotations's layout() function by the
flutter: following function, which probably computed the invalid constraints in question:
flutter: RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:258:13)
flutter: The offending constraints were:
flutter: BoxConstraints(w=382.0, h=Infinity)
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 BoxConstraints.debugAssertIsValid.<anonymous closure>.throwError (package:flutter/src/rendering/box.dart:504:9)
flutter: #1 BoxConstraints.debugAssertIsValid.<anonymous closure> (package:flutter/src/rendering/box.dart:547:21)
flutter: #2 BoxConstraints.debugAssertIsValid (package:flutter/src/rendering/box.dart:551:6)
flutter: #3 RenderObject.layout (package:flutter/src/rendering/object.dart:1549:24)
flutter: #4 RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:258:13)
flutter: #5 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #6 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:13)
flutter: #7 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #8 RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
flutter: #9 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #10 _RenderListTile._layoutBox (package:flutter/src/material/list_tile.dart:892:9)
flutter: #11 _RenderListTile.performLayout (package:flutter/src/material/list_tile.dart:913:30)
flutter: #12 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #13 RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:199:11)
flutter: #14 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #15 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:13)
flutter: #16 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #17 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:13)
flutter: #18 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #19 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:13)
flutter: #20 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #21 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:13)
flutter: #22 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #23 _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:13)
flutter: #24 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #25 RenderSliverList.performLayout (package:flutter/src/rendering/sliver_list.dart:164:27)
flutter: #26 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #27 RenderSliverPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:182:11)
flutter: #28 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
flutter: #29 RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:405:13)
flutter: #30 RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1316:12)
flutter: #31 RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1234:20)
flutter: #32 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1509:7)
flutter: #33 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:768:18)
flutter: #34 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:281:19)
flutter: #35 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:677:13)
flutter: #36 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
flutter: #37 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
flutter: #38 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
flutter: #39 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
flutter: #40 _invoke (dart:ui/hooks.dart:154:13)
flutter: #41 _drawFrame (dart:ui/hooks.dart:143:3)
flutter:
flutter: The following RenderObject was being processed when the exception was fired:
flutter: RenderConstrainedBox#57507 relayoutBoundary=up12 NEEDS-LAYOUT NEEDS-PAINT
flutter: creator: ConstrainedBox â Container â FadeTransition â Stack â StreamBuilder<FileInfo>-[#fb1e3] â
flutter: CachedNetworkImage â IconTheme â Builder â _ListTile â MediaQuery â Padding â SafeArea â â¯
flutter: parentData: <none> (can use size)
flutter: constraints: BoxConstraints(0.0<=w<=382.0, 0.0<=h<=Infinity)
flutter: size: MISSING
flutter: additionalConstraints: BoxConstraints(biggest)
flutter: This RenderObject had the following descendants (showing up to depth 5):
flutter: RenderSemanticsAnnotations#494da NEEDS-LAYOUT NEEDS-PAINT
flutter: RenderImage#98201 NEEDS-LAYOUT NEEDS-PAINT
flutter: ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
flutter: Another exception was thrown: RenderBox was not laid out: RenderConstrainedBox#57507 relayoutBoundary=up12 NEEDS-PAINT
flutter: Another exception was thrown: BoxConstraints forces an infinite height.
flutter: Another exception was thrown: RenderBox was not laid out: RenderConstrainedBox#ac73c relayoutBoundary=up12 NEEDS-PAINT
flutter: Another exception was thrown: BoxConstraints forces an infinite height.
flutter: Another exception was thrown: RenderBox was not laid out: RenderConstrainedBox#95164 relayoutBoundary=up12 NEEDS-PAINT
flutter: Another exception was thrown: BoxConstraints forces an infinite height.
flutter: Another exception was thrown: RenderBox was not laid out: RenderConstrainedBox#9efb3 relayoutBoundary=up12 NEEDS-PAINT
flutter: Another exception was thrown: BoxConstraints forces an infinite height.
flutter: Another exception was thrown: RenderBox was not laid out: RenderConstrainedBox#16fcc relayoutBoundary=up12 NEEDS-PAINT
flutter: Another exception was thrown: BoxConstraints forces an infinite height.
Je dois faire quelques modifications.
Essayez d'ajouter ceci à votre liste vue:
physics: const AlwaysScrollableScrollPhysics(),
Si vous testez sur un émulateur, je suggère de créer l'APK de la version, d'installer l'APK sur votre téléphone Android et de vérifier s'il est est toujours saccadé. Les émulateurs monopolisent les ressources, cela pourrait donc en être une cause.
Enfin, vous pouvez essayer de réduire le nombre d'images, les types d'images ou la taille pour voir si elles sont toujours en retard.
Sinon signalez ce problème sur github, afin que l'équipe Flutter soit au courant.
2 choses
FadeInImage.memoryNetwork au lieu de cached_network_image et / ou ListView (children: List ) au lieu de ListView.separated (itemBuilder:) FadeInImage.memoryNetworkRéf https://flutter.dev/docs/cookbook/images/fading-in-images
Lors de l'exécution de votre exemple de code, je ne peux m'empêcher de remarquer que cached_network_image effectuant un redimensionnement / échantillonnage d'image affectant le thread principal de l'interface utilisateur, il est probable que ce paquet effectue une tâche lourde de calcul sur le thread principal. L'utilisation du livre de cuisine officiel me donne un meilleur résultat (émulateur Android), un exemple de code complet (vous pouvez remplacer kTransparentImage par une autre icône de chargement)
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
void main() {
runApp(MaterialApp(
title: 'List view with network images',
home: ListViewController(),
));
}
class ListViewController extends StatelessWidget {
var imagesArray = [
"http://iastro.shangcarts.com/pub/media/notice/File-1550484786.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550218043.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550217808.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550111913.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550108862.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550024618.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550022739.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549935759.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549935073.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549850545.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549849978.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549008412.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548985261.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548821873.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548731040.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548641672.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548410089.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547774905.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547701178.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547625318.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547624883.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547619153.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547606341.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547606200.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547603338.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547602464.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547454842.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547192524.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547191374.jpg"
];
Widget _imageCell(String imageUrl) {
return ListTile(
leading: CachedNetworkImage(
imageUrl: imageUrl,
placeholder: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
),
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Material(
child: ListView(
children: imagesArray.map((imageUrl) => _imageCell(imageUrl)).toList(),
),
);
}
}
ListView (enfants: List ) Ref https://docs.flutter.io/flutter/widgets/ListView-class.html
Deuxièmement, si vous savez à l'avance que vous allez pour avoir cette liste finie pas si longue, vous voudrez peut-être utiliser ListView (children: List au lieu de ListView.separated (itemBuilder:) , car itemBuilder appellera / appellera les fonctions plus souvent, et pour le moment, les images sont mises en cache (soit par FadeInImage.memoryNetwork ou cached_network_image ) pour le contenu complet uniquement , pas pour la vignette , @ user1462442 mentionne la taille de l'image source, et je suis d'accord avec cette évaluation. Ce que nous pouvons faire est de réduire l’appel à un nombre aussi bas que possible.
Par exemple, code:
import 'package:flutter/material.dart';
import 'package:transparent_image/transparent_image.dart';
void main() {
runApp(MaterialApp(
title: 'List view with network images',
home: ListViewController(),
));
}
class ListViewController extends StatelessWidget {
var imagesArray = [
"http://iastro.shangcarts.com/pub/media/notice/File-1550484786.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550218043.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550217808.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550111913.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550108862.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550024618.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1550022739.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549935759.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549935073.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549850545.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549849978.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1549008412.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548985261.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548821873.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548731040.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548641672.jpeg",
"http://iastro.shangcarts.com/pub/media/notice/File-1548410089.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547774905.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547701178.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547625318.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547624883.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547619153.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547606341.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547606200.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547603338.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547602464.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547454842.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547192524.jpg",
"http://iastro.shangcarts.com/pub/media/notice/File-1547191374.jpg"
];
Widget _imageCell(String imageUrl) {
return ListTile(
leading: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageUrl,
));
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Material(
child:
ListView.separated(
itemBuilder: (BuildContext context, int index) {
return _imageCell(imagesArray[index]);
},
separatorBuilder: (context, index) => Divider(
color: Colors.black,
),
itemCount: imagesArray.length),
);
}
}
Comme dit, vous pouvez appliquer les deux ces recommandations également.
J'ai suivi la route ListView / children car ma liste était également "petite". Fixé.
Il ne semble pas que FadeInImage.memoryNetwork met en cache l'image. Si vous fermez l'application et rouvrez l'image sera à nouveau chargée à partir du réseau, tandis que dans CachedImageNetwork, l'image sera chargée immédiatement à partir du cache. Est-ce le comportement attendu?
vérifiez l'application en mode version.
oui le mode débogage n'est pas fluide, faites-le --profile ou même --release