具有提供程序的可空 class 实例
Nullable class instance with Provider
我有一个名为 User
的 class,它基本上有两个变量。 name
和 age
。另外,我还有一个名为 UserList
的 class。这个 class 的目的是将 user
对象添加到列表中,并 return 该列表。
用户模型
class User with ChangeNotifier{
late String? name;
late int? age;
//set user name;
setName(String name){
this.name=name;
}
//set user age
setAge(int age){
this.age=age;
}
}
用户列表class
class UserList with ChangeNotifier{
final List<User> _list=[];
//add a new user to the list.
void addUserToList(User user){
_list.add(user);
notifyListeners();
}
//return the private list of users.
List<User>getUsers() =>_list;
}
这是场景。我想从一页插入一个值并在第二页上查看插入的值。看下面的图片。在第一页,
- 我插入
age
和 name
值
- 在
User
对象实例中分配这些值 (user.setName, user.setAge
)
- 在
UserList
列表中添加 user
对象实例
- 使用
provider
提供该列表。(Provider.of<UserList>(context).addUserToList(user);
首页
首页代码
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserList()),
ChangeNotifierProvider(create: (context) => User()),
],
child: const MyApp())
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
TextEditingController nameController = TextEditingController();
TextEditingController ageController = TextEditingController();
@override
Widget build(BuildContext context) {
User user =User();
return Scaffold(
backgroundColor: Colors.grey[300],
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: nameController,
decoration: const InputDecoration(
hintText: "Name",
),
),
TextField(
controller: ageController,
decoration: const InputDecoration(
hintText: "Age",
),
),
ElevatedButton(onPressed: (){
//providing userList
user.setName(nameController.text); //setting user name
user.setAge(int.parse(ageController.text)); // setting user age
Provider.of<UserList>(context,listen: false).addUserToList(user); //providing the list of users
nameController.text=""; //after insertion, clearing the text field
ageController.text="";//after insertion, clearing the text field
user=User(); // instantiating a new user object for the following insertion.
Navigator.push(context, MaterialPageRoute(builder: (context)=>const ViewUser()));
}, child: const Text("Submit"))
],
),
),
);
}
}
在第二页上,在 ListView
中显示那些插入的值。让我们回到主要问题。 ListView
的每一项都包裹着一个GestureDetector
,以便能够获得functionality.I希望到目前为止一切都清楚。
问题是; 当我点击每个项目时我想return到first page
。但是,这次 TextField
不应该为空。它必须替换为该项目的值。例如。如果我点击 John Nash
和 43
。第一页必须弹出该列表项的字段值。 为了能够做到这一点,我使用另一个 Provider
来提供 User
对象。但是,由于空安全性,我无法这样做,它给出了关于用户对象为空的错误。有什么有用的想法吗?
第二页
第二页代码
class ViewUser extends StatelessWidget {
const ViewUser({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
List<User> userList = Provider.of<UserList>(context).getUsers();
return Scaffold(
appBar: AppBar(
title: const Text("Users List"),
),
body: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: userList.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
const SizedBox(height: 15,),
GestureDetector(
onTap: (){
Provider.of<User>(context,listen: false)
.setName(userList[index].name!);
Provider.of<User>(context,listen: false)
.setAge(userList[index].age!);
Navigator.push(context, MaterialPageRoute(builder: (context)=>MyHomePage()));
},
child: Container(
height: 50,
color: Colors.amber,
child: Center(
child: Row(
children: [
Text("Name: " + userList[index].name!),
const SizedBox(
width: 40,
),
Text("Age:" + userList[index].age.toString()),
],
),
),
),
),
],
);
}),
);
}
}
当您使用 Navigator.push
时,您可以将用户作为 arguments
。
GestureDetector(
onTap: () {
final user = userList[index];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyHomePage(),
settings: RouteSettings(
arguments: user,
)),
);
},
MyHomePage
构建方法将是
@override
Widget build(BuildContext context) {
User user = User();
User? args = ModalRoute.of(context)?.settings.arguments as User?;
if (args != null) {
nameController.text = args.name ?? "";
ageController.text = args.age.toString();
}
return Scaffold(....
在这种情况下,您也可以使用 Navigator.pop
。
GestureDetector(
onTap: () {
final user = userList[index];
Navigator.pop(context, user);
},
并在 MyHomePage
上接收数据
onPressed: () async {
//....
final data = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ViewUser(),
),
);
if (data != null) {
nameController.text = data.name ?? "";
ageController.text = data.age.toString();
}
更多关于 navigate-with-arguments。
我有一个名为 User
的 class,它基本上有两个变量。 name
和 age
。另外,我还有一个名为 UserList
的 class。这个 class 的目的是将 user
对象添加到列表中,并 return 该列表。
用户模型
class User with ChangeNotifier{
late String? name;
late int? age;
//set user name;
setName(String name){
this.name=name;
}
//set user age
setAge(int age){
this.age=age;
}
}
用户列表class
class UserList with ChangeNotifier{
final List<User> _list=[];
//add a new user to the list.
void addUserToList(User user){
_list.add(user);
notifyListeners();
}
//return the private list of users.
List<User>getUsers() =>_list;
}
这是场景。我想从一页插入一个值并在第二页上查看插入的值。看下面的图片。在第一页,
- 我插入
age
和name
值 - 在
User
对象实例中分配这些值 (user.setName, user.setAge
) - 在
UserList
列表中添加user
对象实例 - 使用
provider
提供该列表。(Provider.of<UserList>(context).addUserToList(user);
首页
首页代码
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserList()),
ChangeNotifierProvider(create: (context) => User()),
],
child: const MyApp())
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
TextEditingController nameController = TextEditingController();
TextEditingController ageController = TextEditingController();
@override
Widget build(BuildContext context) {
User user =User();
return Scaffold(
backgroundColor: Colors.grey[300],
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: nameController,
decoration: const InputDecoration(
hintText: "Name",
),
),
TextField(
controller: ageController,
decoration: const InputDecoration(
hintText: "Age",
),
),
ElevatedButton(onPressed: (){
//providing userList
user.setName(nameController.text); //setting user name
user.setAge(int.parse(ageController.text)); // setting user age
Provider.of<UserList>(context,listen: false).addUserToList(user); //providing the list of users
nameController.text=""; //after insertion, clearing the text field
ageController.text="";//after insertion, clearing the text field
user=User(); // instantiating a new user object for the following insertion.
Navigator.push(context, MaterialPageRoute(builder: (context)=>const ViewUser()));
}, child: const Text("Submit"))
],
),
),
);
}
}
在第二页上,在 ListView
中显示那些插入的值。让我们回到主要问题。 ListView
的每一项都包裹着一个GestureDetector
,以便能够获得functionality.I希望到目前为止一切都清楚。
问题是; 当我点击每个项目时我想return到first page
。但是,这次 TextField
不应该为空。它必须替换为该项目的值。例如。如果我点击 John Nash
和 43
。第一页必须弹出该列表项的字段值。 为了能够做到这一点,我使用另一个 Provider
来提供 User
对象。但是,由于空安全性,我无法这样做,它给出了关于用户对象为空的错误。有什么有用的想法吗?
第二页
第二页代码
class ViewUser extends StatelessWidget {
const ViewUser({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
List<User> userList = Provider.of<UserList>(context).getUsers();
return Scaffold(
appBar: AppBar(
title: const Text("Users List"),
),
body: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: userList.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
const SizedBox(height: 15,),
GestureDetector(
onTap: (){
Provider.of<User>(context,listen: false)
.setName(userList[index].name!);
Provider.of<User>(context,listen: false)
.setAge(userList[index].age!);
Navigator.push(context, MaterialPageRoute(builder: (context)=>MyHomePage()));
},
child: Container(
height: 50,
color: Colors.amber,
child: Center(
child: Row(
children: [
Text("Name: " + userList[index].name!),
const SizedBox(
width: 40,
),
Text("Age:" + userList[index].age.toString()),
],
),
),
),
),
],
);
}),
);
}
}
当您使用 Navigator.push
时,您可以将用户作为 arguments
。
GestureDetector(
onTap: () {
final user = userList[index];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyHomePage(),
settings: RouteSettings(
arguments: user,
)),
);
},
MyHomePage
构建方法将是
@override
Widget build(BuildContext context) {
User user = User();
User? args = ModalRoute.of(context)?.settings.arguments as User?;
if (args != null) {
nameController.text = args.name ?? "";
ageController.text = args.age.toString();
}
return Scaffold(....
在这种情况下,您也可以使用 Navigator.pop
。
GestureDetector(
onTap: () {
final user = userList[index];
Navigator.pop(context, user);
},
并在 MyHomePage
onPressed: () async {
//....
final data = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ViewUser(),
),
);
if (data != null) {
nameController.text = data.name ?? "";
ageController.text = data.age.toString();
}
更多关于 navigate-with-arguments。