问题是:尽管 _isHintBarStack 更新了,为什么 Riverpod 没有重建?
这是我听hintBarStack的地方,(你可以直接跳到Widget的开头和结尾,中间部分用于设计。)
class AnswerBarBubble extends HookWidget {
AnswerBarBubble({Key? key, required this.index}) : super(key: key);
final int index;
@override
Widget build(BuildContext context) {
final usableWidth = MediaQuery.of(context).size.width -
(MediaQuery.of(context).padding.left +
MediaQuery.of(context).padding.right);
final usableHeight = MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.bottom +
MediaQuery.of(context).padding.top);
final _answerBar = useProvider(IndexStackProvider);
final _randomBar = useProvider(randomBarProvider);
final _isHintBarStack = useProvider(hintBarStack).state.contains(index);
final _questionIndex = useProvider(questionIndexProvider).state;
final _question = useProvider(questionsProvider);
var _boxDecor = useState(BoxDecoration(boxShadow: [
BoxShadow(
offset: Offset(usableWidth * 0.005, usableWidth * 0.005),
blurRadius: usableWidth * 0.02,
color: Color.fromRGBO(179, 118, 84, 1),
),
], shape: BoxShape.circle, color: Color.fromRGBO(255, 237, 227, 0.85)));
String char;
try {
var temp = _answerBar[index];
char = _randomBar[temp];
_boxDecor.value = BoxDecoration(boxShadow: [
BoxShadow(
offset: Offset(usableWidth * 0.001, usableWidth * 0.001),
blurRadius: usableWidth * 0.005,
color: Colors.grey.shade300,
),
BoxShadow(
offset: Offset(usableWidth * 0.0008, usableWidth * 0.0008),
blurRadius: usableWidth * 0.004,
color: Colors.grey.shade800,
),
], shape: BoxShape.circle, color: Color.fromRGBO(255, 237, 227, 0.6));
} catch (e) {
char = '';
_boxDecor.value = BoxDecoration(boxShadow: [
BoxShadow(
offset: Offset(usableWidth * 0.005, usableWidth * 0.005),
blurRadius: usableWidth * 0.02,
color: Color.fromRGBO(217, 196, 184, 1),
),
], shape: BoxShape.circle, color: Color.fromRGBO(255, 237, 227, 0.85));
}
return Badge(
showBadge: !_isHintBarStack,
elevation: 10,
badgeContent: Text('${_question[_questionIndex].answer[index]}',
style:
TextStyle(fontSize: usableHeight * 0.020, color: Colors.white)),
badgeColor: Colors.blue,
padding: EdgeInsets.all(usableWidth * 0.01),
alignment: Alignment.center,
position: BadgePosition.topEnd(),
child: AnimatedContainer(
duration: Duration(milliseconds: 200),
child: Center(
child: Text('$char',
style: TextStyle(
fontSize: usableHeight * 0.03, color: Colors.black))),
height: usableWidth * 0.1,
width: usableWidth * 0.1,
decoration: _boxDecor.value));
}
}
状态提供者:
final hintBarStack = StateProvider((ref) {
final questionIndex = ref.watch(questionIndexProvider).state;
final question = ref.read(questionsProvider);
final length = question[questionIndex].answer.length;
final stack = <int>[];
for (var i = 0; i < length; i++) {
stack.add(i);
}
return stack;
});
HintButton : (此按钮更新hintBarStack) (onTap 回调)
class HintButton extends HookWidget {
const HintButton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final usableWidth = MediaQuery.of(context).size.width -
(MediaQuery.of(context).padding.left +
MediaQuery.of(context).padding.right);
final usableHeight = MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.bottom +
MediaQuery.of(context).padding.top);
return ElevatedButton(
onLongPress: () {},
onPressed: () {
if (context.read(hintBarStack).state.length > 0) {
final randInt =
Random().nextInt(context.read(hintBarStack).state.length);
context.read(hintBarStack).state.removeAt(randInt);
}
},
child: Center(
child: Icon(Icons.contact_support_sharp,
color: Colors.black, size: usableHeight * 0.045),
),
style: ElevatedButton.styleFrom(
animationDuration: Duration(milliseconds: 300),
shadowColor: Colors.black,
onSurface: Colors.blueAccent,
onPrimary: Colors.blueAccent.withOpacity(0.8),
shape:
StadiumBorder(side: BorderSide(width: 4, color: Colors.black)),
primary: Colors.blueAccent.withOpacity(0.8),
fixedSize: Size(usableWidth * 0.6, usableHeight * 0.06)));
}
}
让我对riverpod感到困惑的主要事情是,我总是观察到riverpod只会成功重建小部件,当我在文本小部件中使用侦听器时,我的意思是它们可以直接在屏幕上看到,在这些直接的UI使用场景中没有问题。例如在 AnswerBarBubble(第一段代码)中:
Text('$char)
-> Riverpod 在字符更新时重建小部件。(直接 UI 使用)
Badge(showBadge : _isHintBarStack,
-> 当 _isHintBarStack 更新时,Riverpod 不会重建小部件。 (小部件参数)
答案 0 :(得分:1)
感谢 Alex Hartford,问题是 StateProvider 的任务过多,我将 StateProvider 转换为 StateNotifierProvider 并解决了我的问题。
这是 AnswerBubble 小部件:
class AnswerBarBubble extends HookWidget {
AnswerBarBubble({Key? key, required this.index}) : super(key: key);
final int index;
@override
Widget build(BuildContext context) {
final usableWidth = MediaQuery.of(context).size.width -
(MediaQuery.of(context).padding.left +
MediaQuery.of(context).padding.right);
final usableHeight = MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.bottom +
MediaQuery.of(context).padding.top);
final _answerBar = useProvider(IndexStackProvider);
final _randomBar = useProvider(randomBarProvider);
final _isHintBarStack = useProvider(hintBarStack).contains(index);
final _questionIndex = useProvider(questionIndexProvider).state;
final _question = useProvider(questionsProvider);
var _boxDecor = useState(BoxDecoration(boxShadow: [
BoxShadow(
offset: Offset(usableWidth * 0.005, usableWidth * 0.005),
blurRadius: usableWidth * 0.02,
color: Color.fromRGBO(179, 118, 84, 1),
),
], shape: BoxShape.circle, color: Color.fromRGBO(255, 237, 227, 0.85)));
String char;
try {
var temp = _answerBar[index];
char = _randomBar[temp];
_boxDecor.value = BoxDecoration(boxShadow: [
BoxShadow(
offset: Offset(usableWidth * 0.001, usableWidth * 0.001),
blurRadius: usableWidth * 0.005,
color: Colors.grey.shade300,
),
BoxShadow(
offset: Offset(usableWidth * 0.0008, usableWidth * 0.0008),
blurRadius: usableWidth * 0.004,
color: Colors.grey.shade800,
),
], shape: BoxShape.circle, color: Color.fromRGBO(255, 237, 227, 0.6));
} catch (e) {
char = '';
_boxDecor.value = BoxDecoration(boxShadow: [
BoxShadow(
offset: Offset(usableWidth * 0.005, usableWidth * 0.005),
blurRadius: usableWidth * 0.02,
color: Color.fromRGBO(217, 196, 184, 1),
),
], shape: BoxShape.circle, color: Color.fromRGBO(255, 237, 227, 0.85));
}
return Stack(
alignment: Alignment.center,
clipBehavior: Clip.hardEdge,
children: [
Badge(
showBadge: !_isHintBarStack,
elevation: 10,
badgeContent: Text('${_question[_questionIndex].answer[index]}',
style: TextStyle(
fontSize: usableHeight * 0.020, color: Colors.white)),
badgeColor: Colors.blue,
padding: EdgeInsets.all(usableWidth * 0.01),
alignment: Alignment.center,
position: BadgePosition.topEnd(),
child: AnimatedContainer(
duration: Duration(milliseconds: 200),
child: Center(
child: Text('$char',
style: TextStyle(
fontSize: usableHeight * 0.03,
color: Colors.black))),
height: usableWidth * 0.1,
width: usableWidth * 0.1,
decoration: _boxDecor.value))
],
);
}
}
StateNotifierProvider :
final hintBarStack = StateNotifierProvider<HintBarStack, List<int>>((ref) {
final _question = ref.read(questionsProvider);
final _index = ref.watch(questionIndexProvider).state;
final _length = _question[_index].answer.length;
final _state = <int>[];
for (var i = 0; i < _length; i++) {
_state.add(i);
}
return HintBarStack(_state);
});
提示按钮:
class HintButton extends HookWidget {
const HintButton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final usableWidth = MediaQuery.of(context).size.width -
(MediaQuery.of(context).padding.left +
MediaQuery.of(context).padding.right);
final usableHeight = MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.bottom +
MediaQuery.of(context).padding.top);
return ElevatedButton(
onLongPress: () {},
onPressed: () {
if (context.read(hintBarStack).length > 0) {
final randInt = Random().nextInt(context.read(hintBarStack).length);
context.read(hintBarStack.notifier).pop(randInt);
}
},
child: Center(
child: Icon(Icons.contact_support_sharp,
color: Colors.black, size: usableHeight * 0.045),
),
style: ElevatedButton.styleFrom(
animationDuration: Duration(milliseconds: 300),
shadowColor: Colors.black,
onSurface: Colors.blueAccent,
onPrimary: Colors.blueAccent.withOpacity(0.8),
shape:
StadiumBorder(side: BorderSide(width: 4, color: Colors.black)),
primary: Colors.blueAccent.withOpacity(0.8),
fixedSize: Size(usableWidth * 0.6, usableHeight * 0.06)));
}
}
状态通知程序:
class HintBarStack extends StateNotifier<List<int>> {
HintBarStack(List<int> state) : super(state);
void pop(int index) {
var temp = state;
temp.removeAt(index);
state = [...temp];
}
}