Я парень из 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,
),