ListView дает так много мусора при смене страницы во Flutter - PullRequest
0 голосов
/ 27 мая 2020

Я парень из android разработки, и мне очень нравится флаттер. Но у меня возникли некоторые проблемы с ListView, такая проблема похожа на то, что основной поток выполняет много задач, и я решаю это с помощью AsyncTask на android, но во Flutter это дает мне в официальных документах.

Поскольку Flutter является однопоточным и запускает событие l oop (например, Node.js), вам не нужно беспокоиться об управлении потоками или порождении фоновых потоков. Если вы выполняете работу, связанную с вводом-выводом, такую ​​как доступ к диску или сетевой вызов, вы можете безопасно использовать async / await, и все готово. Если, с другой стороны, вам нужно выполнять интенсивную вычислительную работу, которая заставляет ЦП загружаться, вы хотите переместить его в Isolate, чтобы избежать блокировки события l oop, как если бы вы не выполняли любую работу из основного поток в Android.

В моем доме это виджет с отслеживанием состояния, и вот код:

return new WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          automaticallyImplyLeading: false,
          centerTitle: true,
          backgroundColor: ThemeColor.AppPrimaryColor, // status bar color
          brightness: Brightness.dark, // status bar brightness
          elevation: 5,
          title: AppBarContent(),
        ),
        drawer: MenuBar(),
        body: Container(
          child: SingleChildScrollView(
            controller: _scrollController,
            child: Column(
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Container(
                      child: CategorySlider(),
                    ),
                    SizedBox(
                      height: screenHeight * 0.02,
                    ),
                    Container(
                      child: BannerSlider(),
                    ),
                    SizedBox(
                      height: screenHeight * 0.03,
                    ),
                    Container(
                      child: Container(
                        margin: EdgeInsets.only(left: 20.0),
                        child: Row(
                          mainAxisSize: MainAxisSize.max,
                          children: <Widget>[
                            Text(
                              'Vitrines em destaque',
                              style: CustomFontStyle.titleList(),
                            ),
                          ],
                        ),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(9.0),
                      child: CompanyList(true),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );

Внизу у меня есть строка, которая вызывает виджет CompanyList:

          Padding(
              padding: const EdgeInsets.all(9.0),
              child: CompanyList(true),
            ),

И это мой класс CompanyList

class CompanyList extends StatefulWidget {
  final filtered;
  final isShrink;
  final MasterCategoryModel masterCategoryModel;
  CompanyList(
      [this.isShrink = false, this.masterCategoryModel, this.filtered = false]);
  // const CompanyList({Key key}) : super(key: key);
  @override
  State<StatefulWidget> createState() => new CompanyListState();
}

class CompanyListState extends State<CompanyList> {
  CompanyController companyController = new CompanyController();
  CompanyService companyService;
  Map<String, dynamic> companyList = {};
  bool loadingData = true;
  bool loadData = true;
  bool loadMoreData = false;
  int pageCounter = 1;

  @override
  void initState() {
    super.initState();
    companyService = Provider.of<CompanyService>(context, listen: false);
    companyService.loadMoreData$.listen((value) {
      if (value) {
        if (loadData) {
          loadData = false;
          getMoreData();
        }
      }
    });
    widget.filtered
        ? getCompanyByMsCateg(widget.masterCategoryModel)
        : getRandomActiveCompanys();
  }

  @override
  void dispose() {
    super.dispose();
  }

  getRandomActiveCompanys() {
    setState(() {
      loadingData = true;
    });
    companyController.getRandomActiveCompanys(pageCounter).then((value) {
      setState(() {
        pageCounter++;
        companyList = value;
        loadingData = false;
      });
    }).catchError((error) {
      print(error);
      setState(() {
        loadingData = false;
      });
    });
  }

  getMoreData() {
    setState(() {
      loadMoreData = true;
    });
    companyController.getRandomActiveCompanys(pageCounter).then((value) {
      setState(() {
        pageCounter++;
        companyList['data'] = companyList['data']..addAll(value['data']);
        loadMoreData = false;
      });
    }).catchError((error) {
      print(error);
      setState(() {
        loadMoreData = false;
      });
    });
  }

  getCompanyByMsCateg(MasterCategoryModel masterCategoryModel) {
    setState(() {
      loadingData = true;
    });
    companyController
        .getCompanysByMsgCateg(masterCategoryModel.master_category_id)
        .then((value) {
      setState(() {
        companyList.addAll(value);
        loadingData = false;
      });
    }).catchError((error) {
      print(error);
      setState(() {
        loadingData = false;
      });
    });
  }

  getMoreCompanyData() {
    setState(() {
      // companyList.add(totalCompanyList[i]);
    });
    Future.delayed(const Duration(milliseconds: 3000), () {
      loadData = true;
    });
  }

  getCompanyData(company) {
    Navigator.push(
      context,
      PageTransition(
        type: PageTransitionType.rightToLeft,
        child: CompanyScreen(
          company: company,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final double screenHeight = MediaQuery.of(context).size.height;
    final double screenWidth = MediaQuery.of(context).size.width;

    return !loadingData
        ? ListView.builder(
            addAutomaticKeepAlives: true,
            shrinkWrap: widget.isShrink ? true : false,
            physics: ClampingScrollPhysics(),
            padding: const EdgeInsets.all(8),
            itemCount: companyList['data'].length,
            itemBuilder: (BuildContext context, int index) {
              return GestureDetector(
                onTap: () => getCompanyData(companyList['data'][index]),
                child: Container(
                  child: Column(
                    children: <Widget>[
                      Row(
                        mainAxisSize: MainAxisSize.max,
                        children: <Widget>[
                          Flexible(
                            flex: 2,
                            child: Container(
                              height: screenHeight * 0.12,
                              decoration: new BoxDecoration(
                                border: Border.all(
                                  color: ThemeColor.AppBorderGrey,
                                ),
                                borderRadius: new BorderRadius.only(
                                  topLeft: const Radius.circular(5.0),
                                  bottomLeft: const Radius.circular(5.0),
                                ),
                              ),
                              child: Center(
                                child:
                                    companyList['data'][index]['image'] != null
                                        ? Container(
                                            height: 45,
                                            width: 45,
                                            child: ClipRRect(
                                              borderRadius: BorderRadius.all(
                                                  Radius.circular(20.0)),
                                              child: Image.network(
                                                '${MainConfig.storageDoc + companyList['data'][index]['image']}',
                                                width: 42,
                                                height: 42,
                                                cacheWidth: 42,
                                                cacheHeight: 42,
                                                fit: BoxFit.cover,
                                              ),
                                            ),
                                          )
                                        : new Container(
                                            width: screenWidth * 0.13,
                                            height: screenWidth * 0.13,
                                            decoration: new BoxDecoration(
                                              shape: BoxShape.circle,
                                              image: new DecorationImage(
                                                fit: BoxFit.fill,
                                                image: AssetImage(
                                                    'assets/icons/error/no_image_v2.png'),
                                              ),
                                            ),
                                          ),
                              ),
                            ),
                          ),
                          Flexible(
                            flex: 3,
                            child: Container(
                              height: screenHeight * 0.12,
                              decoration: new BoxDecoration(
                                border: Border.all(
                                  color: ThemeColor.AppBorderGrey,
                                ),
                                borderRadius: new BorderRadius.only(
                                  topRight: const Radius.circular(5.0),
                                  bottomRight: const Radius.circular(5.0),
                                ),
                              ),
                              child: Center(
                                child: Text(
                                  '${companyList['data'][index]['storename']}',
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                      SizedBox(
                        height: 10.0,
                      ),
                    ],
                  ),
                ),
              );
            })
        : Center(
            child: Column(
              children: <Widget>[
                SizedBox(
                  height: 10.0,
                ),
                Center(
                  child: SpinKitThreeBounce(
                    color: ThemeColor.AppPrimaryColor,
                    size: 30.0,
                  ),
                ),
              ],
            ),
          );
  }
}

Если я изменяю страницу и go обратно, мое приложение всегда оказывается ненужным и закрывается, поэтому я провожу небольшое исследование и обнаруживаю, что проблема была проблема с CacheImages, поэтому в GitHub я нахожу решение для установки фиксированных cacheWidth и cacheHeight, и это заставляет мое приложение не трескать sh, а иметь мусор. Поэтому я подумываю изолировать функцию, загружающую этот виджет. Что мне делать?

  child: Image.network(
                   '${MainConfig.storageDoc + companyList['data'][index]['image']}',
                    width: 42,
                    height: 42,
                    cacheWidth: 42,
                    cacheHeight: 42,
                    fit: BoxFit.cover,
                  ),
...