class ListNumbersPage extends GetView<MyController> {
final colors = [
Colors.red,
Colors.green,
Colors.pinkAccent,
Colors.blue,
Colors.grey,
Colors.cyan,
];
final random = Random();
@override
Widget build(BuildContext context) {
Get.put(MyController());
return Scaffold(
appBar: AppBar(title: const Text('ListNumbersPage')),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: controller.listOfFiles.length,
itemBuilder: (_, index) {
final currentFile = controller.listOfFiles[index];
return Container(
padding: const EdgeInsets.symmetric(vertical: 32),
color: colors[random.nextInt(colors.length)],
child: Row(
children: [
Obx(
() {
MyLogs.warning('UPDATED INDEX : $index');
return MyIconButton(
onTap: () {
doLike(controller.listOfSelection ?? [], currentFile.value.fileId, index);
},
iconData: FontAwesomeIcons.solidHeart,
color: isExist(controller.listOfSelection ?? [], currentFile.value.fileId, index)
? isLiked(controller.listOfSelection ?? [], currentFile.value.fileId)
? AppColor.redDark
: AppColor.white
: AppColor.white,
);
},
),
Text(controller.listOfFiles[index].value.fileId),
],
),
);
},
),
),
],
),
);
}
}
bool isExist(List<Rx<LikeModel>> listOfSelection, String fileId, int index) {
try {
if (listOfSelection.length >= index) {
final item = listOfSelection.firstWhereOrNull((e) => e.value.fileId == fileId);
return item != null;
} else {
return false;
}
} catch (e) {
MyLogs.debug(e.toString());
return false;
}
}
bool isLiked(List<Rx<LikeModel>> listOfSelection, String fileId) {
try {
return listOfSelection.firstWhere((e) => e.value.fileId == fileId).value.isLiked;
} catch (e) {
MyLogs.debug(e.toString());
return false;
}
}
void doLike(List<Rx<LikeModel>> listOfSelection, String fileId, int index) {
try {
final item = listOfSelection.firstWhere((element) => element.value.fileId == fileId);
final index = listOfSelection.indexOf(item);
final isLiked = item.value.isLiked;
listOfSelection[index].value = item.value.copyWith(
isLiked: !isLiked,
);
} catch (e) {
MyLogs.debug(e.toString());
}
}
class MyController extends GetxController {
final listOfFiles = [
"IMAGE001",
"IMAGE002",
"IMAGE003",
"IMAGE004",
"IMAGE005",
"IMAGE006",
"IMAGE007",
"IMAGE008",
"IMAGE009",
"IMAGE010",
].map((e) => LikeModel(e, false).obs).toList();
List<Rx<LikeModel>>? listOfSelection;
@override
void onInit() {
listOfSelection = listOfFiles;
super.onInit();
}
}
class LikeModel {
String fileId;
bool isLiked;
LikeModel(this.fileId, this.isLiked);
LikeModel copyWith({
String? fileId,
bool? isLik
}) {
return LikeModel(
fileId ?? this.fileId,
isLiked ?? this.isLiked,
);
}
}
我在 Flutter 应用程序中遇到一个问题,其中有一个 ListView 显示项目列表,每个项目都包含一个“like”按钮。当我按下特定项目的“like”按钮时,问题就出现了 - 整个 ListView 被重建,而不是只更新那个特定的“like”按钮,从而导致性能开销。
我想要实现的是仅更新数据(如状态)已更改的特定“点赞”按钮小部件,而不影响列表项的其余部分。
我尝试过使用各种状态管理技术,例如 Obx、GetBuilder,甚至尝试过 Provider,但似乎都没有提供仅更新目标小部件的解决方案。
有人可以指导我如何在关联数据发生变化时有效地更新 ListView 中的相关小部件吗?任何见解、代码片段或示例将不胜感激。
谢谢!
如果我理解正确,您的小部件通过更改“MyController”获得新状态。
如果有一种方法可以完成您需要的操作,而无需不断地为 MyController 设置新状态,您可以将此代码放入有状态小部件中。然后你可以在那里做你的事情,当你完成并想要设置一个新状态时,更新你的控制器。然后整个ListView只重建一次。
Container(
padding: const EdgeInsets.symmetric(vertical: 32),
color: colors[random.nextInt(colors.length)],
child: Row(
children: [
Obx(
() {
MyLogs.warning('UPDATED INDEX : $index');
return MyIconButton(
onTap: () {
doLike(controller.listOfSelection ?? [], currentFile.value.fileId, index);
},
iconData: FontAwesomeIcons.solidHeart,
color: isExist(controller.listOfSelection ?? [], currentFile.value.fileId, index)
? isLiked(controller.listOfSelection ?? [], currentFile.value.fileId)
? AppColor.redDark
: AppColor.white
: AppColor.white,
);
},
),
Text(controller.listOfFiles[index].value.fileId),
],
),
);