我正在尝试学习Flutter和Riverpod,并尝试使用简洁的代码。我只是注意到我的小部件被调用了两次。如何避免进行不必要的操作?
我的项目只是一个导航栏,根据我们单击的按钮加载视图
我的NavigationBar屏幕:
class NavigationBarScreen extends HookWidget
{
@override
Widget build(BuildContext context) {
print('build navigationScreen');
final _pageModel = useProvider(navigationProvider.state);
return SafeArea(
child: Scaffold(
body : context.read(navigationProvider).buildScreen(_pageModel.pageState),
bottomNavigationBar: Container(
margin: EdgeInsets.only(left : 8, right : 8, bottom: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(20), topLeft: Radius.circular(20)),
boxShadow: [
BoxShadow(color: AppColors.colorShadowLight, spreadRadius: 0, blurRadius: 10),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(50.0),
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
backgroundColor: AppColors.colorBgDark,
fixedColor: AppColors.colorContrastOrange,
unselectedItemColor: AppColors.colorFontLight2,
currentIndex: _pageModel.navigationIndexItem,
showSelectedLabels: false,
showUnselectedLabels: false,
onTap: context.read(navigationProvider).selectPage,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
title: Text('Settings'),
),
],
),
),
),
),
);
}
}
我的导航通知程序:
enum NavigationBarState
{
HOME, PROFIL
}
class NavigationNotifier extends StateNotifier<NavigationBarModel>
{
NavigationNotifier() : super(_initialPage);
static const int _initialIndex = 0;
static const NavigationBarState _initialState = NavigationBarState.HOME;
static const _initialPage = NavigationBarModel(pageState : _initialState, navigationIndexItem : _initialIndex);
void selectPage(int i)
{
switch (i)
{
case 0:
state = NavigationBarModel(pageState : NavigationBarState.HOME, navigationIndexItem : i);
break;
case 1:
state = NavigationBarModel(pageState : NavigationBarState.PROFIL, navigationIndexItem : i);
break;
}
}
Widget buildScreen(NavigationBarState page)
{
switch (page)
{
case NavigationBarState.HOME:
return HomeScreen();
break;
case NavigationBarState.PROFIL:
return Text("Page under construction");
break;
}
return null;
}
}
我的navigationBarModel:
class NavigationBarModel {
const NavigationBarModel({this.pageState, this.navigationIndexItem});
final NavigationBarState pageState;
final int navigationIndexItem;
}
在运行检查器中,我有这个:
I/flutter (32738): build navigationScreen
I/flutter (32738): build homeScreen
I/flutter (32738): build navigationScreen
I/flutter (32738): build homeScreen
编辑::在我的navigationBar屏幕中,我已对此进行了更改:
body : context.read(navigationProvider).buildScreen(_pageModel.pageState),
由此:
body : useProvider(navigationProvider).buildScreen(_pageModel.pageState),
必须在onPressed,onTap等中使用context.read(),但结果相同,我的navigationBarScreen被调用了两次... < / p>
答案 0 :(得分:1)
我无法运行您的代码,因为缺少某些部分,但是我最好的猜测是,因为您同时在监视提供程序本身和提供程序状态,所以这就是为什么它被调用两次的原因。
@override
Widget build(BuildContext context) {
print('build navigationScreen');
// Here you are listening to the state
final _pageModel = useProvider(navigationProvider.state);
return SafeArea(
child: Scaffold(
// Here you are listening to the provider
body : context.read(navigationProvider).buildScreen(_pageModel.pageState),
我建议您重构StateNotifier,而不是从navigationProvider状态中获取pageModel并将其传递回navigationProvider中。
class NavigationNotifier extends StateNotifier<NavigationBarModel>
{
NavigationNotifier() : super(_initialPage);
static const int _initialIndex = 0;
static const NavigationBarState _initialState = NavigationBarState.HOME;
static const _initialPage = NavigationBarModel(pageState : _initialState, navigationIndexItem : _initialIndex);
void selectPage(int i)
{
switch (i)
{
case 0:
state = NavigationBarModel(pageState : NavigationBarState.HOME, navigationIndexItem : i);
break;
case 1:
state = NavigationBarModel(pageState : NavigationBarState.PROFIL, navigationIndexItem : i);
break;
}
}
Widget buildScreen()
{
switch (state.pageState)
{
case NavigationBarState.HOME:
return HomeScreen();
break;
case NavigationBarState.PROFIL:
return Text("Page under construction");
break;
}
return null;
}
}
然后从构建方法的顶部删除final _pageModel = useProvider(navigationProvider.state);
。