我的小部件在切换不应显示的位置时会重建



我有一个StatefulWidget,基本上包括一个背景小部件(播放视频)和前景HUDColumn的小部件。可以通过在ElevatedButton上粘贴来切换后期可见性。

视图数StatefulWidget从远程基于云的数据库获取该计数,并且在实际获取时显示CircularProgressIndicator

这个小部件是HUD的一部分。

为什么当我切换HUD时它会再次获取数据库?如何将计数器保存在内存中呢?

这是主要的小部件:

@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(title: Text(widget.ad.title)),
body: Stack(
children: [
GestureDetector(
onTap: () {
if (_displayHud.value == false) {
_displayHud.value = true;
}
},
// == the background image
child: _buildBackgroundImage(context)),
// === The foreground UI
FutureBuilder(
future: widget.ad.getOwnerUser,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
final owner = snapshot.data!;
return ValueListenableBuilder(
valueListenable: _displayHud,
builder: (context, value, child) {
return Visibility(
visible: _displayHud.value,
replacement: Align(
alignment: Alignment.topRight,
child: ElevatedButton(
onPressed: () {
if (_displayHud.value == false) {
_displayHud.value = true;
}
},
child: const Icon(
Icons.fullscreen_exit,
))),
child: Padding(
padding: const EdgeInsets.all(20),
child: _buildForegroundUi(context,
watchingUser: widget.watchingUser,
owner: owner)),
);
});
})
],
));
}

这里是count Widget:


/// A widget that display a coun from a future
class _CounterWidget extends StatefulWidget {
/// The icon to display
final IconData iconData;
/// The future that fetches the count
final Future<int> getCount;
/// The press callback
final void Function()? onPressed;
const _CounterWidget(
{required this.iconData, required this.getCount, this.onPressed});
@override
State<_CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<_CounterWidget> {
int? _value;
Exception? _error;
@override
void initState() {
_asyncInitState();
super.initState();
}
void _asyncInitState() async {
widget.getCount.then((value) {
if (!mounted) return;
setState(() {
_value = value;
});
}).catchError((e) {
if (!mounted) return;
setState(() {
_error = e;
});
});
}
@override
Widget build(BuildContext context) {
const viewerIconColor = Colors.white;
final viewerTextStyle =
Theme.of(context).textTheme.caption?.copyWith(color: Colors.white);
final countWidget = _error != null
? const Icon(Icons.error)
: _value == null
? const Center(child: CircularProgressIndicator())
: Text("$_value", style: viewerTextStyle);
// === Likes
if (widget.onPressed == null) {
return Column(children: [
Icon(widget.iconData, color: viewerIconColor),
countWidget
]);
}
return ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
//side: BorderSide(color: Colors.red)
))),
onPressed: widget.onPressed,
child: Column(children: [Icon(widget.iconData), countWidget]));
}
}

我以前遇到过类似的问题。你可以看到这个家伙用StreamBuilder解释。既然这是一个视频,我就剪一段。你可以在这里看到:

  • 问题:https://youtube.com/clip/UgkxU3QOcatZOh1bSRe3KwEEValakNU5josE
  • 解决方案:https://youtube.com/clip/UgkxME0hQM6r0bXzFB43nAi5kZCKt1DV0IMn

综上所述,您可以将您的未来函数指定为state变量。

class _YourClassWidgetState extends State<YourClass> {
final _futureFunc =  widget.ad.getOwnerUser(); // declare as state variable
....
// === The foreground UI
FutureBuilder(
future: _futureFunc,

注意:我使用setState()来更新我的UI,因为你正在使用ValueNotifier(),我不知道它会有相同的行为。您可以在您这边试试。

但我的假设是一样的。因为更新ValueListenableBuilder同时也更新了FutureBuilder*cmiiw

最新更新