Flutter长名单表现不佳

whhtz7ly  于 2023-10-22  发布在  Flutter
关注(0)|答案(2)|浏览(118)

我尝试使用Listview和Sliverlist,但我的列表的性能非常慢。即使项目是从互联网上加载的,滚动也非常慢。
有没有人对慢代码有什么想法?

import 'dart:typed_data';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:impex_shop/bloc/warenkorb_bloc.dart';
import 'package:impex_shop/data/articlepodo.dart';
import 'package:impex_shop/routenames.dart';
import 'package:impex_shop/services/repository.dart';
import 'package:impex_shop/styles/impex_icons.dart';
import 'package:impex_shop/styles/impex_styles.dart';
import 'package:impex_shop/utils/utils.dart';
import 'package:impex_shop/widgets/myfuturebuilder.dart';

class SearchResultsWidget extends StatefulWidget {
  final Map<String, String> search;

  SearchResultsWidget(this.search);

  @override
  _SearchResultsWidgetState createState() =>
      _SearchResultsWidgetState(this.search);
}

class _SearchResultsWidgetState extends State<SearchResultsWidget> {
  Map<String, String> search;
  Future<ArticleIdList> _articleIds;

  _SearchResultsWidgetState(this.search);

  @override
  void initState() {
    super.initState();
    _articleIds = Repository().queryArticleSearch(search);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _articleIds,
      //showProgressIndicator: true,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done &&
            snapshot.hasData) {
          ArticleIdList articleIds = snapshot.data;
          if (articleIds.articleIds.length == 0) {
            return Container(
              padding: EdgeInsets.symmetric(
                  horizontal: ImpexStyle.horizontalPadding),
              child: Text('Kein Artikel gefunden'),
            );
          }
          return CustomScrollView(
            slivers: <Widget>[
              SliverList(
                delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                    if (index == 0) {
                      return Container(
                        height: ImpexStyle.verticalPadding,
                      );
                    }
                    Future<Article> article = Repository()
                        .queryArticleDetails(articleIds.articleIds[index - 1]);
                    return MyFutureBuilder(
                      future: article,
                      builder: (context, article) {
                        return SearchResultLineWidget(article: article);
                      },
                    );
                  },
                  childCount: articleIds.articleIds.length + 1,
                ),
              )
            ],
          );
        } else if (snapshot.hasError) {
          return Row(
            children: <Widget>[
              Icon(
                Icons.error,
                color: ImpexColors.errorColor,
                size: 30,
              ),
              Expanded(
                child: Text(
                  '${snapshot.error}',
                  style: TextStyle(color: ImpexColors.errorColor),
                ),
              )
            ],
          );
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}

class SearchResultLineWidget extends StatefulWidget {
  const SearchResultLineWidget({this.article});

  final Article article;

  @override
  State<StatefulWidget> createState() {
    return SearchResultLineState(article);
  }
}

class SearchResultLineState extends State<SearchResultLineWidget> {
  SearchResultLineState(this._article);

  final Article _article;
  Future<String> _articleImageData;

  @override
  void initState() {
    super.initState();
    _articleImageData = Repository().queryArticleImage(
      _article.id,
      width: ImpexStyle.imageSize,
      height: ImpexStyle.imageSize,
    );
  }

  @override
  Widget build(BuildContext context) {
    WarenkorbBloc warenkorbBloc = BlocProvider.of<WarenkorbBloc>(context);
    bool isInWarenkorb = (warenkorbBloc.currentState as WarenkorbLoaded)
            .warenkorbLines[_article.id] !=
        null;

    return Column(
      children: <Widget>[
        FlatButton(
          onPressed: (() {
            Navigator.pushNamed(context, RouteName.ARTICLE_DETAIL,
                arguments: _article.id);
          }),
          child: Row(
            children: <Widget>[
              FutureBuilder<String>(
                future: _articleImageData,
                builder: (context, snapshot) {
                  if (snapshot.hasData &&
                      snapshot.connectionState == ConnectionState.done) {
                    var imageData = snapshot.data;
                    if (imageData.isEmpty || imageData == 'null')
                      return Container(
                        width: ImpexStyle.imageSize.toDouble(),
                        height: ImpexStyle.imageSize.toDouble(),
                        child: EmptyImageIcon(),
                      );
                    return Container(
                      height: ImpexStyle.imageSize.toDouble(),
                      width: ImpexStyle.imageSize.toDouble(),
                      child: Stack(children: <Widget>[
                        Image(
                          image: MemoryImage(
                            Uint8List.fromList(imageData.codeUnits),
                          ),
                        ),
                        isInWarenkorb
                            ? Icon(FontAwesomeIcons.shoppingCart)
                            : Center(),
                      ]),
                    );
                  } else if (snapshot.hasError) {
                    return Container(
                      width: ImpexStyle.imageSize.toDouble(),
                      height: ImpexStyle.imageSize.toDouble(),
                      child: Text(snapshot.error),
                    );
                  }

                  return Container(
                    width: ImpexStyle.imageSize.toDouble(),
                    height: max(96, ImpexStyle.imageSize.toDouble()),
                    child: Center(),
                  );
                },
              ),
              Container(width: ImpexStyle.horizontalPadding),
              Flexible(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Row(
                      children: <Widget>[
                        Expanded(
                          child: Text(
                            _article.no,
                            style: ImpexStyle.fontStyleSmall,
                          ),
                        ),
                        Spacer(),
                        PriceLagerWidget(_article),
                      ],
                    ),
                    Text(_article.name, style: ImpexStyle.fontStyleNormal)
                  ],
                ),
              )
            ],
          ),
        ),
        Divider(color: ImpexColors.dividerColor),
      ],
    );
  }
}

class PriceLagerWidget extends StatelessWidget {
  PriceLagerWidget(this._article)
      : _articlePrice = Repository().queryArticlePrice(_article.id);

  final Article _article;
  final Future<ArticlePrice> _articlePrice;

  @override
  Widget build(BuildContext context) {
    return MyFutureBuilder<ArticlePrice>(
      future: _articlePrice,
      builder: (context, articlePrice) {
        String priceString = getPriceString(articlePrice, context);
        return Row(
          children: <Widget>[
            Row(
              children: <Widget>[
                _article.isRaffleWin
                    ? RaffleWinIcon()
                    : Text('€', style: ImpexStyle.fontStyleSmall),
                Text(' $priceString ', style: ImpexStyle.fontStyleSmall)
              ],
            ),
            AvailabilityIcon(this._article.availabilityColor)
          ],
        );
      },
    );
  }
}
f3temu5u

f3temu5u1#

我认为使用ListView.builder可能会对你有所帮助,因为它只渲染可见的项目。
这是一篇关于widget optimization的文章,它解释了构建一些小部件时的性能差异。

qxsslcnc

qxsslcnc2#

ListView.builder(itemCount:rows,prototypeItem:ListTile(),itemBuilder:(context,index){ ListTile()}确保设置prototypeItem,否则性能仍然很差。

相关问题