实现setstat和bind变量



我试图从另一个dart文件获取和显示2个变量值,("int myId"one_answers"String myMenu"),这些变量会随着每次"onTap"小部件,我的代码工作,但只有当我做一个"热重载",我认为我需要放一个"setstate";在某个地方,但我很难实现它。

我认为问题就在那里,我的小部件文本返回"null"对我来说,但是如果我点击菜单按钮并进行"热重新加载",那就没问题了。

displayText.dart

import 'package:flutter/material.dart';
import './menu.dart';
class display extends StatefulWidget {
int myId;
String myMenu;
display(this.myId, this.myMenu);
@override
_displayState createState() => _displayState();
}
class _displayState extends State<display> {
Future myVarUsed() async {
//Each press on the button return the value
setState(() {
print('myIdDsiplay: ${widget.myId}'); // null
print('myMenuDisplay : ${widget.myMenu}'); // null
});
}
@override
void initState() {
super.initState();
myVarUsed();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
height: 250,
width: 250,
child: Row(
children: [
Text('My ID is : ${widget.myId}'),
Text('My menu is : ${widget.myMenu}'),
],
),
);
}
}

这个文件包含一个滚动条内的菜单,每个按钮返回ID和名称(按钮的),并将其存储在2个变量("int myId"one_answers"String myMenu"),我想传递。

menu.dart

import 'package:flutter/material.dart';
import './mylist.dart';
import './displayText.dart';
class Menu extends StatefulWidget {
static int myId;
static String myMenu;
@override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
Container scrollList() {
final PageController controller = PageController(initialPage: 1, keepPage: true, viewportFraction: 0.35);
return Container(
color: Colors.red,
height: 90,
child: PageView.builder(
scrollDirection: Axis.horizontal,
controller: controller,
itemCount: listdata.length,
physics: BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Container(
child: gestureDetector_Ontap(index),
);
},
),
);
}
GestureDetector gestureDetector_Ontap(int index) {
return GestureDetector(
onTap: () {
Menu.myId = listdata[index].id;
Menu.myMenu = listdata[index].menuObj;
display(Menu.myId, Menu.myMenu);
print('myIDMenu ${Menu.myId}');
print('myMenuMenu ${Menu.myMenu}');
},
child: Container(
alignment: AlignmentDirectional.center,
child: Text(
'${listdata[index].menuObj}',
),
),
);
}
Widget build(BuildContext context) {
return Container(
child: scrollList(),
);
}
}

这个文件包含我的列表和他的类

mylist.dart

class listModel {
int id;
String menuObj;
listModel(this.id, this.menuObj);
}
List listdata = [
listModel(0, 'Menu01'),
listModel(1, 'Menu02'),
listModel(2, 'Menu03'),
listModel(3, 'Menu04'),
listModel(4, 'Menu05')
];

和容器

main.dart

import 'package:flutter/material.dart';
import './menu.dart';
import './displayText.dart';
import './mylist.dart';
void main() {
runApp(MyHomePage());
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: Column(
children: <Widget>[
Menu(),
display(Menu.myId, Menu.myMenu),
],
),
),
),
);
}
}

问题

你是这样定义Menu的:

class Menu extends StatefulWidget {
static int myId;
static String myMenu;
@override
_MenuState createState() => _MenuState();
}

当你的应用程序启动时,myIdmyMenu是未初始化的变量,因此它们被隐式地设置为null。


_MyHomePageState内部,调用

display(Menu.myId, Menu.myMenu)

由于你还没有初始化Menu.myIdMenu.myMenu,它们仍然是空的。


当你点击手势检测器时,你这样初始化Menu.myIdMenu.myMenu:

Menu.myId = listdata[index].id;
Menu.myMenu = listdata[index].menuObj;
display(Menu.myId, Menu.myMenu);
print('myIDMenu ${Menu.myId}');
print('myMenuMenu ${Menu.myMenu}');

现在,Menu.myIdMenu.myMenu被定义为非空值。但是,这个不会更新容器的display(Menu.myId, Menu.myMenu),所以他们仍然是空的,你需要自己更新它。

的解决方案我在代码中添加了注释,指出了更好的方法:

import 'package:flutter/material.dart';
// Avoid displaying the warning "Name types using UpperCamelCase."
class Display extends StatefulWidget {
// Make these fields final and the constructor const
final int myId;
final String myMenu;

const Display(this.myId, this.myMenu);

@override
_DisplayState createState() => _DisplayState();
}
// Avoid displaying the warning "Name types using UpperCamelCase."
class _DisplayState extends State<Display> {
// You don't need this Future nor this initState
// 
// Future myVarUsed() async {
//   setState(() {
//     print('myIdDsiplay: ${widget.myId}'); // null
//     print('myMenuDisplay : ${widget.myMenu}'); // null
//   });
//  }
// 
// @override
// void initState() {
//   super.initState();
//   myVarUsed();
// }
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
height: 250,
width: 250,
child: Row(
children: [
Text('My ID is : ${widget.myId}'),
Text('My menu is : ${widget.myMenu}'),
],
),
);
}
}
class Menu extends StatefulWidget {
// Avoid using mutable static fields
// static int myId;
// static String myMenu;

// To simplify, you can add a onChanged callback to 
// be triggered whenever you change `myId` and `myMenu`
final void Function(int myId, String myMenu) onChanged;

const Menu({this.onChanged});

@override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
Container scrollList() {
final PageController controller = PageController(initialPage: 1, keepPage: true, viewportFraction: 0.35);
return Container(
color: Colors.red,
height: 90,
child: PageView.builder(
scrollDirection: Axis.horizontal,
controller: controller,
itemCount: listdata.length,
physics: BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Container(
child: gestureDetectorOntap(index),
);
},
),
);
}
// Avoid displaying the warning "Name non-constant identifiers using lowerCamelCase."
GestureDetector gestureDetectorOntap(int index) {
return GestureDetector(
onTap: () {
// Make these local variables
int myId = listdata[index].id;
String myMenu = listdata[index].menuObj;

// Call the `onChanged` callback
widget.onChanged(myId, myMenu);

// This widget is being thrown away
// display(Menu.myId, Menu.myMenu);
print('myIDMenu $myId');
print('myMenuMenu $myMenu');
},
child: Container(
alignment: AlignmentDirectional.center,
child: Text(
'${listdata[index].menuObj}',
),
),
);
}
Widget build(BuildContext context) {
return Container(
child: scrollList(),
);
}
}
// Avoid the warning "Name types using UpperCamelCase."
class ListModel {
// You can make these fields final and the constructor const
final int id;
final String menuObj;

const ListModel(this.id, this.menuObj);
}
// You can make this list const to avoid modifying it unintentionally later
const List<ListModel> listdata = [
ListModel(0, 'Menu01'),
ListModel(1, 'Menu02'),
ListModel(2, 'Menu03'),
ListModel(3, 'Menu04'),
ListModel(4, 'Menu05')
];
void main() {
runApp(MyHomePage());
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// Create fields to store the current `myId` and current `myMenu`
int myId;
String myMenu;

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: Column(
children: <Widget>[
// Add the `onChanged` callback here, updating this widget state
Menu(
onChanged: (newMyId, newMyMenu) {
setState(() {
myId = newMyId;
myMenu = newMyMenu;
});
}
),
// Access the current values here
Display(myId, myMenu),
],
),
),
),
);
}
}

最新更新