Flutter riverpod 小部件调用两次
Flutter riverpod widget is calling twice
我正在尝试学习 Flutter 和 Riverpod 并尝试编写干净的代码。我只是注意到我的小部件被调用了两次。如何避免做不必要的操作?
我的项目只是一个导航栏,它根据我们单击的按钮加载视图
我的 NavigationBarScreen :
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;
}
}
我的导航栏模型:
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
编辑: 在我的 navigationBarScreen 中,我更改了这个:
body : context.read(navigationProvider).buildScreen(_pageModel.pageState),
通过这个 :
body : useProvider(navigationProvider).buildScreen(_pageModel.pageState),
context.read()必须用在onPressed,onTap,...但是我的结果是一样的,我的navigationBarScreen被调用了两次...
我无法 运行 您的代码,因为缺少某些部分,但我最好的猜测是,因为您正在观察提供者本身和提供者状态,这就是它被调用两次的原因。
@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);
。
我正在尝试学习 Flutter 和 Riverpod 并尝试编写干净的代码。我只是注意到我的小部件被调用了两次。如何避免做不必要的操作?
我的项目只是一个导航栏,它根据我们单击的按钮加载视图
我的 NavigationBarScreen :
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;
}
}
我的导航栏模型:
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
编辑: 在我的 navigationBarScreen 中,我更改了这个:
body : context.read(navigationProvider).buildScreen(_pageModel.pageState),
通过这个 :
body : useProvider(navigationProvider).buildScreen(_pageModel.pageState),
context.read()必须用在onPressed,onTap,...但是我的结果是一样的,我的navigationBarScreen被调用了两次...
我无法 运行 您的代码,因为缺少某些部分,但我最好的猜测是,因为您正在观察提供者本身和提供者状态,这就是它被调用两次的原因。
@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);
。