架构/逻辑问题-在这种情况下,我如何只重建一个消费者小部件?-Riverpod



我真的陷入了困境&我不知道如何在保持功能的同时重新设计以顺利修复此问题。我试着在树中向上移动可重复使用的小部件,但这很令人困惑,也不起作用。我正在创建一个Flutter包,以防这可能会引起一些帮助。这是一个特定于我错误的体系结构/逻辑的问题,但也是一个关于如何使用Riverpod提供程序创建可重复使用的小部件的一般问题,以便只更新必要的小部件。

我的问题是我有一个";"可重复使用";小部件-";NumberButtonAnimation"&我在我的";SequentialNavigator";在这种情况下为父级。它们都是按钮,都在监听我的逻辑服务文件navigatorServices中的pageIndex值。因此,当页面索引更改时,它们都会重新生成,这当然是昂贵且不必要的。

如何添加逻辑或重新设计,以便只需要重建移动按钮?

如果我认为钥匙可能有用,我的想法会正确吗?

/// LOGIC
final navigatorServices = ChangeNotifierProvider((ref) => NavigatorServices());
class NavigatorServices extends ChangeNotifier {
StateCRUD stateCRUD = StateCRUD();
int pageIndex = 1;
int indexCount = 5;
void nextPage() {
if (pageIndex < indexCount) {
pageIndex++;
saveState();
notifyListeners();
}
}
void previousPage() {
if (pageIndex > 1) {
pageIndex--;
saveState();
notifyListeners();
}
}
double buttonPosition(int buttonNumber) {
double totalHeight = Get.height;
double topPadding = WidgetsBinding.instance!.window.padding.top;
double bottomPadding = WidgetsBinding.instance!.window.padding.bottom;
double safeArea = totalHeight - (topPadding + bottomPadding);
const double buttonWithPadding = 35.0;
late double buttonTop;
List<int> pageIndexes = [];
int index = 0;
// Current or past screen
if (pageIndex >= buttonNumber) buttonTop = ((buttonWithPadding * buttonNumber) - buttonWithPadding);
if (pageIndex < buttonNumber) {
while (index < indexCount + 1) {
pageIndexes.add(index);
index++;
}
buttonTop = (buttonWithPadding * pageIndexes[buttonNumber]) + safeArea / 1.5;
}
return buttonTop;
}
...
}

/// NUMBER BUTTON ANIMATION WIDGET
class NumberButtonAnimation extends StatelessWidget {
const NumberButtonAnimation({Key? key, required this.buttonNumber}) : super(key: key);
final int buttonNumber;
@override
Widget build(BuildContext context) {
return Consumer(
builder: (context, ref, child) {
print('Number button consumer built');
return AnimatedPositioned(
top: ref.watch(navigatorServices).buttonPosition(buttonNumber),
curve: Curves.bounceOut,
duration: const Duration(milliseconds: 500),
child: NumberButton(number: buttonNumber),
);
},
);
}
}
/// PARENT WIDGET
class SequentialNavigator extends StatelessWidget {
const SequentialNavigator({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: 43.0,
height: double.maxFinite,
child: Stack(
fit: StackFit.expand,
alignment: Alignment.topCenter,
children: [
const NumberButtonAnimation(buttonNumber: 1),
const NumberButtonAnimation(buttonNumber: 2),
const NumberButtonAnimation(buttonNumber: 3),
const NumberButtonAnimation(buttonNumber: 4),
const NumberButtonAnimation(buttonNumber: 5),
],
),
);
}
}

当我点击下一个或上一个时它看起来是什么样子:

<5> flutter: Number button consumer built

这将打印5次,指示所有小部件正在重建,但在任何更改时只有一个按钮需要重建。。。

您可以使用provider.select(...)通过只获取您需要的来过滤重建

一个使用示例是:

Consumer(
builder: (context, ref, child) {
print('Number button consumer built');
return AnimatedPositioned(
top: ref.watch(navigatorServices.select((service) => service.buttonPosition(buttonNumber)),
...
);
},
);

最新更新