【问题标题】:Flutter App Performance Issues with Long List长列表的 Flutter 应用程序性能问题
【发布时间】:2021-09-05 04:18:58
【问题描述】:

我有一个颤振应用程序,用户可以在其中将项目添加到存储在 firebase 中的列表中。用户一次最多可以添加 1000 个项目。最初这不是问题,但随着列表项的增加,应用程序变得越来越慢,直到在列表中大约 1000 个项目后一次添加多个项目时,由于内存使用,应用程序崩溃 -

线程 #10,名称 = 'io.flutter.1.ui',停止原因 = EXC_RESOURCE RESOURCE_TYPE_MEMORY(限制=1450 MB,未使用=0x0)

如何改进代码以提高性能。我想保留 Stream 的设置,因为它可以让我动态地过滤列表。这里还有一个信息是 WidgetA 和 WidgetB 也都使用 Stream Data 来显示列表中的列表项数。

为了便于阅读,我的代码做了一些简化:

主屏幕类:

Widget content(context) {
double h = MediaQuery.of(context).size.height; //screen height
double w = MediaQuery.of(context).size.width; //screen width



return StreamProvider<List<Activity>>.value(
    catchError: (_, __) => null,
    value: DatabaseService().activities(widget.uid),
    builder: (context, snapshot) {
      return SafeArea(
        child: Container(
          //color: Theme.of(context).backgroundColor, //SkyHookTheme.background,
          child: Scaffold(
            backgroundColor: Colors.transparent,
            body: NotificationListener<ScrollNotification>(
              onNotification: _handleScrollNotification,
              child: Stack(children: [
                ListView(
                  controller: _scrollController,
                  children: <Widget>[
                    Column(
                      children: <Widget>[
                   
                        WidgetA(),
                        WidgetB(),
                        ActivityList(),    //List of User Activities

                      ],
                    )
                  ],
                ),
              
              ]),
            ),
          ),
        ),
      );
    });
}

ActivityList类Listview构建:

ListView buildList(List<Activity> acts){
items = ListView.builder(
  shrinkWrap: true,
  physics: ClampingScrollPhysics(),
  scrollDirection: Axis.vertical,
  itemCount: len,
  itemBuilder: (context, index) {
    return ActivityTile(activity: acts[index], number: acts.length - (index));
  },
);


return items;

}

任何提示/提示我可以如何改进这一点将不胜感激。

谢谢!

【问题讨论】:

    标签: firebase performance flutter listview


    【解决方案1】:

    您必须分页才能实现流畅的执行 一次加载 10 个文档 滚动控制器的帮助检查您是否在列表的末尾 然后加载接下来的 10 个文档 高效的方式。

    【讨论】:

    • 您好,谢谢!如果可能的话,我想避免这种情况,因为在这种情况下,我的 WidgetB() 是一个搜索过滤器,它允许用户直接在完整列表中搜索关键字。这对 1000 件以下的物品非常有效。这就是为什么如果可以的话,我不想重建它或限制功能。
    【解决方案2】:

    使用 sliversList 小部件代替“listview”。 参见 sliversList 和 sliverscomponents 示例here

    【讨论】:

      【解决方案3】:

      我认为@AmitSingh 的建议是最好的,但是如果您想一次性加载数据,那么您可以在分页中获取数据,但不是在用户滚动时而是在您获得第一批数据时。

      【讨论】:

        【解决方案4】:

        是的,您应该使用分页或延迟加载!对于大多数移动设备来说,一次读取和渲染 1000 个文档的工作量太大。 相反,您应该像这样加载您的文档

        import 'package:cloud_firestore/cloud_firestore.dart';  
        Firestore firestore = Firestore.instance
        
        class LongList extends StatefulWidget {
        

        @覆盖 _LongListState createState() => _LongListState(); }

        class _LongListState extends State<LongList> {
        
        List<DocumentSnapshot> products = []; // stores fetched products  
        bool isLoading = false; // track if products fetching  
        bool hasMore = true; // flag for more products available or not  
        int documentLimit = 10; // documents to be fetched per request  
        DocumentSnapshot lastDocument; // flag for last document from where next   10 records to be fetched  
        ScrollController _scrollController = ScrollController(); // listener for    listview scrolling
        
        getProducts() async {  
               if (!hasMore) {  
                print('No More Products');  
                return;  
               }  
           if (isLoading) {  
             return;  
           }  
           setState(() {  
             isLoading = true;  
           });  
         QuerySnapshot querySnapshot;  
           if (lastDocument == null) {  
             querySnapshot = await firestore  
                 .collection('products')  
                 .orderBy('name')  
                 .limit(documentLimit)  
                 .getDocuments();  
           } else {  
             querySnapshot = await firestore  
                 .collection('products')  
                 .orderBy('name')  
                 .startAfterDocument(lastDocument)  
                 .limit(documentLimit)  
                 .getDocuments();  
             print(1);  
           }  
           if (querySnapshot.documents.length < documentLimit) {  
             hasMore = false;  
           }  
           lastDocument = querySnapshot.documents[querySnapshot.documents.length - 1];  
           products.addAll(querySnapshot.documents);  
           setState(() {  
             isLoading = false;  
           });  
           }  
        
          void initState(){
          getProducts();
          _scrollController.addListener(() {
          double maxScroll = _scrollController.position.maxScrollExtent;
          double currentScroll = _scrollController.position.pixels;
          double delta = MediaQuery.of(context).size.height * 0.20;
          if (maxScroll - currentScroll <= delta) {
            getProducts();
          }
          });
          _pageManager = PageManager();
        
          super.initState();
          }  
          Widget build(BuildContext context) {  
           return Scaffold(  
             appBar: AppBar(  
               title: Text('Flutter Pagination with Firestore'),  
             ),  
             body: Column(children: [  
               Expanded(  
                 child: products.length == 0  
                     ? Center(  
                         child: Text('No Data...'),  
                       )  
                     : ListView.builder(  
                         controller: _scrollController,  
                         itemCount: products.length,  
                         itemBuilder: (context, index) {  
                           return ListTile(  
                             contentPadding: EdgeInsets.all(5),  
                             title: Text(products[index]['name']),  
                             subtitle: Text(products[index]  ['short_desc']),  
                           );  
                         },  
                       ),  
               ),  
               isLoading  
                   ? Container(  
                       width: MediaQuery.of(context).size.width,  
                       padding: EdgeInsets.all(5),  
                       color: Colors.yellowAccent,  
                       child: Text(  
                         'Loading',  
                         textAlign: TextAlign.center,  
                         style: TextStyle(  
                           fontWeight: FontWeight.bold,  
                         ),  
                       ),  
                     )  
                   : Container()  
             ]),  
           );  
         }  
        

        }

        【讨论】:

          猜你喜欢
          • 2010-12-17
          • 2020-04-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-22
          • 2018-07-18
          • 1970-01-01
          • 2014-12-08
          相关资源
          最近更新 更多