缓慢的滚动在无限的滚动中颤动



我正在尝试为我的列表实现无限滚动,它运行得很好,唯一的问题是滚动有点慢,一点也不平滑,我不知道为什么。有没有一种方法可以让我的滚动更流畅?这是我的列表类:


class QrqcListView extends StatefulWidget {
@override
_QrqcListViewState createState() => _QrqcListViewState();
}
late Future<QrqcDetails?> futureQrqc;
late ScrollController _controller;
List<Qrqc>? myList;
String? label;
int _count = 20;
int pageSize = 1;
bool isBottom = false;
bool isLoading = false;
bool _visible = true;
class _QrqcListViewState extends State<QrqcListView> {
void _showToast(BuildContext context) {
final scaffold = ScaffoldMessenger.of(context);
scaffold.showSnackBar(
SnackBar(
content: const Text('No more data to load'),
action: SnackBarAction(
label: 'UNDO', onPressed: scaffold.hideCurrentSnackBar),
),
);
}
List<TypeSettings> listTypes = [];
void initState() {
Future.delayed(const Duration(seconds: 8), () {
//asynchronous delay
if (this.mounted) {
setState(() {
_visible = false;
});
}
});
_controller = ScrollController();
Provider.of<MyQrqcListViewModel>(context, listen: false).fetchMyQrqc();
fetchTypes();
super.initState();
}
fetchTypes() async {
listTypes = (await SettingsViewModel().fetchTypes());
setState(() {
listTypes;
});
}
@override
Widget build(BuildContext context) {
var myQrqcListViewModel = Provider.of<MyQrqcListViewModel>(context);
myList = myQrqcListViewModel.articlesList;
List<Qrqc>? qrqcList = myList;
Future<List<Qrqc>>? _fetch(int count) {
return Future.delayed(
Duration(seconds: 1),
() => qrqcList!.take(count).toList(),
);
}
_controller.addListener(() {
var triggerFetchMoreSize = 0.5 * _controller.position.maxScrollExtent;
if (_controller.position.pixels ==
(_controller.position.maxScrollExtent - 50)) {
setState(() {
isBottom = true;
});
if (qrqcList!.length == _count) {
setState(() {
_count += 20;
});
}
print(_count);
} else {
setState(() {
isBottom = false;
});
}
print(isBottom);
});
QrqcDetails? result;
String? type;
String? setTypeLabel(int j) {
for (int j = 0; j < qrqcList!.length; j++) {
for (int i = 0; i < listTypes.length; i++) {
if (listTypes[i].id == qrqcList![j].typeID) {
qrqcList[j].typeName = listTypes[i].label;
}
}
}
}
return FutureBuilder(
future: _fetch(_count),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
String? backgroundImage;
return ScrollListener(
threshold: 0.8,
builder: (context, controller) {
final listView = ListView.builder(
controller: _controller,
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: qrqcList!.length,
itemBuilder: (BuildContext context, int index) {
List<String>? typeNames;
String? typeName;
List<String>? _setTypeName() {
for (int i = 0; i < listTypes.length; i++) {
if (listTypes[i].id == qrqcList[index].typeID) {
typeNames!.add(listTypes[i].label);
}
}
return typeNames;
print(listTypes);
}
String? backgroundImage;
String? _setImage() {
setTypeLabel(index);
if (qrqcList![index].typeName == "Delivery") {
backgroundImage = "assets/icons/delivery.png";
} else if (qrqcList![index].typeName == "Security") {
backgroundImage = "assets/icons/security.png";
} else if (qrqcList![index].typeName == "Quality") {
backgroundImage = "assets/icons/quality.png";
} else if (qrqcList![index].typeName == "Cost") {
backgroundImage = "assets/icons/Cost.png";
} else if (qrqcList![index].typeName == "People") {
backgroundImage = "assets/icons/people.png";
} else {
backgroundImage = "assets/icons/unknown.png";
}
print("list types: $type");
print("_mTitle: $backgroundImage");
return backgroundImage; // here it returns your _backgroundImage value
}
return Column(
children: [
ConditionalBuilder(
condition: qrqcList[index].status == 'INIT',
builder: (context) => QrqcBody(
child: QrqcCard(
child: QrqcCardBody(
color: Colors.orange,
text: qrqcList[index].status,
leading:
QrqcCardLeaing(imgPath: _setImage()),
trailing: QrqcCardtrailing(
text:
qrqcList[index].progress.toString(),
percent:
qrqcList[index].progress.toString(),
),
title: qrqcList[index].id.toString(),
subtitle: qrqcList[index].title,
chlidren: [
QrqcDetailsCardFirstRow(
product: "No product",
role:
qrqcList[index].role ?? "no role",
),
const SizedBox(height: 10),
QrqcDetailsCardSecondRow(
perim:
qrqcList[index].perimeterName ??
"no perim",
date: convertDateTimeDisplay(
qrqcList[index].createdAt!),
),
const SizedBox(height: 10),
],
)),
),
fallback: null),
ConditionalBuilder(
condition: qrqcList[index].status == 'SUBMITTED',
builder: (context) => QrqcBody(
child: QrqcCard(
child: QrqcCardBody(
color: Colors.blueAccent,
text: 'SUB',
leading:
QrqcCardLeaing(imgPath: _setImage()),
trailing: QrqcCardtrailing(
text:
qrqcList[index].progress.toString(),
percent:
qrqcList[index].progress.toString(),
),
title: qrqcList[index].id.toString(),
subtitle: qrqcList[index].title,
chlidren: [
QrqcDetailsCardFirstRow(
product: "No product",
role:
qrqcList[index].role ?? "no role",
),
const SizedBox(height: 10),
QrqcDetailsCardSecondRow(
perim:
qrqcList[index].perimeterName ??
"no perim",
date: convertDateTimeDisplay(
qrqcList[index].createdAt!),
),
const SizedBox(height: 10),
],
)),
),
fallback: null),
ConditionalBuilder(
condition: qrqcList[index].status == 'VALIDATED',
builder: (context) => QrqcBody(
child: QrqcCard(
child: QrqcCardBody(
color: Colors.green,
text: 'Valid',
leading:
QrqcCardLeaing(imgPath: _setImage()),
trailing: QrqcCardtrailing(
text:
qrqcList[index].progress.toString(),
percent:
qrqcList[index].progress.toString(),
),
title: qrqcList[index].id.toString(),
subtitle: qrqcList[index].title,
chlidren: [
QrqcDetailsCardFirstRow(
product: "No product",
role:
qrqcList[index].role ?? "no role",
),
const SizedBox(height: 10),
QrqcDetailsCardSecondRow(
perim:
qrqcList[index].perimeterName ??
"no perim",
date: convertDateTimeDisplay(
qrqcList[index].createdAt!),
),
const SizedBox(height: 10),
],
)),
),
fallback: null),
ConditionalBuilder(
condition: qrqcList[index].status == 'ESCALATED',
builder: (context) => QrqcBody(
child: QrqcCard(
child: QrqcCardBody(
color: Colors.red,
text: 'ESCAL',
leading:
QrqcCardLeaing(imgPath: _setImage()),
trailing: QrqcCardtrailing(
text:
qrqcList[index].progress.toString(),
percent:
qrqcList[index].progress.toString(),
),
title: qrqcList[index].id.toString(),
subtitle: qrqcList[index].title,
chlidren: [
QrqcDetailsCardFirstRow(
product: "No product",
role:
qrqcList[index].role ?? "no role",
),
const SizedBox(height: 10),
QrqcDetailsCardSecondRow(
perim:
qrqcList[index].perimeterName ??
"no perim",
date: convertDateTimeDisplay(
qrqcList[index].createdAt!),
),
const SizedBox(height: 10),
],
)),
),
fallback: null)
],
);
});
return Stack(
children: [
listView,
ConditionalBuilder(
condition: isBottom == true && _visible == true,
builder: (context) => Positioned(
left: 100,
right: 100,
bottom: 0,
child: Container(
width: 80,
height: 80,
child:
Center(child: CircularProgressIndicator()),
),
),
fallback: null),
],
);
},
loadNext: () {
if (qrqcList!.length == _count) {
setState(() {
_count += 20;
});
}
print(_count);
},
);
} else if (snapshot.hasError) {
return NoDataUI();
}
return Center(
child: CircularProgressIndicator(),
);
});
}
}
String convertDateTimeDisplay(String date) {
String createdAt = date.substring(1, 10);
final DateFormat displayFormater = DateFormat('yyyy-MM-dd');
final DateFormat serverFormater = DateFormat('dd-MM-yyyy');
final DateTime displayDate = displayFormater.parse(createdAt);
final String formatted = serverFormater.format(displayDate);
return formatted;
}
class ScrollListener extends StatefulWidget {
final Widget Function(BuildContext, ScrollController) builder;
final VoidCallback loadNext;
final double threshold;
ScrollListener({
required this.threshold,
required this.builder,
required this.loadNext,
});
@override
_ScrollListener createState() => _ScrollListener();
}
class _ScrollListener extends State<ScrollListener> {
ScrollController _controller = ScrollController();
@override
void initState() {
super.initState();
_controller.addListener(() {
final rate = _controller.offset / _controller.position.maxScrollExtent;
if (widget.threshold <= rate) {
widget.loadNext();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.builder(context, _controller);
}
}


我使用了两个已处理的方法,在我的ListView类和滚动侦听器类中,这两个类给了我以下异常:

a scrollcontroller was used after being disposed

所以我删除了ListView类中的disposed方法,我认为这会导致滚动速度变慢,我该如何解决这个问题?我将感谢你的帮助

部分原因可能是您在默认debug模式下运行应用程序。当处于活动状态时,Flutter会在应用程序运行时编译代码,导致其速度减慢(例如滚动大/无限列表时(。它的优点是调试时具有热重新加载功能。

在配置文件模式下运行应用程序是否可以防止问题发生?您可以在运行配置(Android Studio(中使用flutter run --profile--profile标志作为"附加运行参数"。

顺便说一句,我建议在小部件被破坏时处理控制器

最新更新