首页 > 解决方案 > 长列表的 Flutter 应用程序性能问题

问题描述

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

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

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

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

主屏类:

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;

}

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

谢谢!

标签: firebaseperformanceflutterlistview

解决方案


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

import 'package:cloud_firestore/cloud_firestore.dart';  
Firestore firestore = Firestore.instance

class LongList extends StatefulWidget {

@override _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()  
     ]),  
   );  
 }  

}


推荐阅读