将变量从 MaterialPageRoute 传递到自定义小部件
Pass variable from MaterialPageRoute to custom widget
一些背景知识:这里是 Flutter 菜鸟,正在尝试构建“添加到收藏夹”功能。项目列表位于 PHP/MySQL 数据库中,我在 FirstScreen 上使用 http 访问该数据库。当用户点击其中一个列表项时,他们会被重定向到 SecondScreen,我使用 MaterialPageRoute 传递 'itemId',它有一个添加到收藏夹按钮。 'itemId' 的收藏项使用 sqflite 在本地存储。我可以使用 StatefulWidget 访问 'itemId',但我没有成功尝试创建一个自定义的 Stateful 小部件来管理无状态小部件,就像这个 Flutter example on interactivity,即我无法访问 'itemId' 来自自定义有状态小部件。
代码片段:
MaterialPageRoute(
builder: (context) => SecondScreen(
itemId: item[index].itemId,
我的sqflite check收藏功能:
Future<bool> checkFavourited(String itemId) async {
Database db = await instance.database;
var bookmarked = await db.query(table,
where: 'itemId = ?',
whereArgs: [itemId]);
return bookmarked.isEmpty ? false : true;
}
正在工作的 StatefulWidget:
bool _isFavourited = false;
void isFavourited() async {
final isFavourited =
await DatabaseHelper.instance.checkFavourited(widget.itemId);
setState(() {
_isFavourited = isFavourited;
});
}
但我尝试在 StatelessWidget 中执行此操作失败了。到目前为止我有:
class SecondScreen extends StatelessWidget {
final String itemId;
SecondScreen({
Key key,
@required this.itemId,
我收到以下错误消息:
The getter 'itemId' isn't defined for the type 'FavouritedButton'.
当我尝试这样做时:
class FavouritedButton extends StatefulWidget {
@override
_FavouritedButtonState createState() => _FavouritedButtonState();
}
class _FavouritedButtonState extends State<FavouritedButton> {
bool _isFavourited = false;
void isFavourited() async {
final isFavourited =
await DatabaseHelper.instance.checkBookmark(widget.itemId);
setState(() {
_isFavourited = isFavourited;
});
}
@override
Widget build(BuildContext context) {
return IconButton(
icon: isFavourited
? Icon(Icons.bookmark)
: Icon(
Icons.bookmark_border,
),
我已阅读 Flutter's Simple app state management and List of state management approaches 篇文章,但我可能是错的,但是否有比 Provider 或 FutureBuilder 更简单的解决方案?
我知道这是一篇很长的文章 post,如果有人能给我一些建议,我将不胜感激。提前致谢!
干净的代码方法,通过将小部件重建隔离到尽可能窄的范围内,您做的是正确的,但需要将 id
移动到有状态小部件。
class FavouritedButton extends StatefulWidget {
final String itemId;
FavouritedButton({required this.itemId});
@override
_FavouritedButtonState createState() => _FavouritedButtonState();
}
class _FavouritedButtonState extends State<FavouritedButton> {
//add initState here, and keep the rest of your widget as it is.
@override
void initState() {
isFavourited();
super.initState();
}
然后在您的无状态小部件中:
class SecondScreen extends StatelessWidget {
final String itemId;
const SecondScreen({Key? key, required this.itemId}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(children:[
Text('write some text about your widget or $itemId'),
FavouritedButton(itemId:itemId)
]);
}
}
这只会重建您最喜欢的按钮。
根据您的代码片段,您正在使用 Construstor
传递数据。但是你没有在 FavouritedButton
中声明 itemId
。正如@Huthaifa Muayyad 所说,它会得到解决。如果你喜欢将数据作为路由参数传递,你需要像这样传递
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => FavouritedButton (),
settings: RouteSettings(
arguments: itemId,
)),
);
在 widgetSide 上接收
Widget build(BuildContext context) {
final data = ModalRoute.of(context)!.settings;
我描述更多here
一些背景知识:这里是 Flutter 菜鸟,正在尝试构建“添加到收藏夹”功能。项目列表位于 PHP/MySQL 数据库中,我在 FirstScreen 上使用 http 访问该数据库。当用户点击其中一个列表项时,他们会被重定向到 SecondScreen,我使用 MaterialPageRoute 传递 'itemId',它有一个添加到收藏夹按钮。 'itemId' 的收藏项使用 sqflite 在本地存储。我可以使用 StatefulWidget 访问 'itemId',但我没有成功尝试创建一个自定义的 Stateful 小部件来管理无状态小部件,就像这个 Flutter example on interactivity,即我无法访问 'itemId' 来自自定义有状态小部件。
代码片段:
MaterialPageRoute(
builder: (context) => SecondScreen(
itemId: item[index].itemId,
我的sqflite check收藏功能:
Future<bool> checkFavourited(String itemId) async {
Database db = await instance.database;
var bookmarked = await db.query(table,
where: 'itemId = ?',
whereArgs: [itemId]);
return bookmarked.isEmpty ? false : true;
}
正在工作的 StatefulWidget:
bool _isFavourited = false;
void isFavourited() async {
final isFavourited =
await DatabaseHelper.instance.checkFavourited(widget.itemId);
setState(() {
_isFavourited = isFavourited;
});
}
但我尝试在 StatelessWidget 中执行此操作失败了。到目前为止我有:
class SecondScreen extends StatelessWidget {
final String itemId;
SecondScreen({
Key key,
@required this.itemId,
我收到以下错误消息:
The getter 'itemId' isn't defined for the type 'FavouritedButton'.
当我尝试这样做时:
class FavouritedButton extends StatefulWidget {
@override
_FavouritedButtonState createState() => _FavouritedButtonState();
}
class _FavouritedButtonState extends State<FavouritedButton> {
bool _isFavourited = false;
void isFavourited() async {
final isFavourited =
await DatabaseHelper.instance.checkBookmark(widget.itemId);
setState(() {
_isFavourited = isFavourited;
});
}
@override
Widget build(BuildContext context) {
return IconButton(
icon: isFavourited
? Icon(Icons.bookmark)
: Icon(
Icons.bookmark_border,
),
我已阅读 Flutter's Simple app state management and List of state management approaches 篇文章,但我可能是错的,但是否有比 Provider 或 FutureBuilder 更简单的解决方案?
我知道这是一篇很长的文章 post,如果有人能给我一些建议,我将不胜感激。提前致谢!
干净的代码方法,通过将小部件重建隔离到尽可能窄的范围内,您做的是正确的,但需要将 id
移动到有状态小部件。
class FavouritedButton extends StatefulWidget {
final String itemId;
FavouritedButton({required this.itemId});
@override
_FavouritedButtonState createState() => _FavouritedButtonState();
}
class _FavouritedButtonState extends State<FavouritedButton> {
//add initState here, and keep the rest of your widget as it is.
@override
void initState() {
isFavourited();
super.initState();
}
然后在您的无状态小部件中:
class SecondScreen extends StatelessWidget {
final String itemId;
const SecondScreen({Key? key, required this.itemId}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(children:[
Text('write some text about your widget or $itemId'),
FavouritedButton(itemId:itemId)
]);
}
}
这只会重建您最喜欢的按钮。
根据您的代码片段,您正在使用 Construstor
传递数据。但是你没有在 FavouritedButton
中声明 itemId
。正如@Huthaifa Muayyad 所说,它会得到解决。如果你喜欢将数据作为路由参数传递,你需要像这样传递
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => FavouritedButton (),
settings: RouteSettings(
arguments: itemId,
)),
);
在 widgetSide 上接收
Widget build(BuildContext context) {
final data = ModalRoute.of(context)!.settings;
我描述更多here