我是Flutter开发的新手,我试图显示下拉列表的选定值,但我无法使其正常工作。
该下拉菜单并未将其显示为所选内容,而是继续显示,好像什么都没有选择一样。请帮助我解决问题。
这是我的代码
import 'dart:convert';
import 'package:sqlliteapp/db_helper.dart';
import 'package:sqlliteapp/user_model.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
class SqliteDropdown extends StatefulWidget {
@override
SqliteDropdownState createState() {
return new SqliteDropdownState();
}
}
class SqliteDropdownState extends State<SqliteDropdown> {
DatabaseHelper db = DatabaseHelper();
//Add data to db
_saveData() async {
UserModel user1 = UserModel(
"test",
"test",
"test@gmail.com",
"test",
);
UserModel user2 = UserModel(
"test1",
"test1",
"test1@gmail.com",
"test",
);
await db.saveData(user1);
await db.saveData(user2);
}
@override
void initState() {
super.initState();
_saveData();
}
UserModel _currentUser;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Fetching data from Sqlite DB - DropdownButton'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
FutureBuilder<List<UserModel>>(
future: db.getUserModelData(),
builder: (BuildContext context,
AsyncSnapshot<List<UserModel>> snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return DropdownButton<UserModel>(
items: snapshot.data
.map((user) => DropdownMenuItem<UserModel>(
child: Text(user.name),
value: user,
))
.toList(),
onChanged: (UserModel value) {
setState(() {
_currentUser = value;
});
},
isExpanded: true,
//value: _currentUser,
hint: Text('Select User'),
);
}),
SizedBox(height: 20.0),
_currentUser != null
? Text(
"Name: " +
_currentUser.name +
"\n Email: " +
_currentUser.email +
"\n Username: " +
_currentUser.username +
"\n Password: " +
_currentUser.password,
)
: Text("No User selected"),
],
),
),
);
}
}
下拉列表没有将其显示为所选内容,而是一直保持选中状态。请支持我解决问题
答案 0 :(得分:1)
我们可以在items
参数中看到,DropdownButton
将获得
选项定义
DropdownButton<UserModel>(
items: snapshot.data // <-- this define options
.map((user) => DropdownMenuItem<UserModel>(
child: Text(user.name),
value: user,
))
.toList(),
onChanged: (UserModel value) {
setState(() {
_currentUser = value;
});
},
value: _currentUser,
);
选择一个选项后,就会出现问题。下拉列表将在StatefulWidget中修改_currentUser并执行setState
。
默认情况下,通过触发setState
,Flutter小部件将再次触发build
方法。
FutureBuilder<List<UserModel>>(
future: db.getUserModelData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return DropdownButton<UserModel>(
items: snapshot.data
.map((user) => DropdownMenuItem<UserModel>(
child: Text(user.name),
value: user,
))
.toList(),
onChanged: (UserModel value) {
setState(() {
_currentUser = value; // <-- Will trigger re-build on StatefulWidget
});
},
value: _currentUser,
);
}),
这对我们来说是强制性的,不要在内部构建方法中初始化。当我们需要删除FutureBuilder时,我们还需要初始化screenStage
@override
void initState() {
_screenStage = "loading"; // <-- set "loading" to display CircularProgress
onceSetupDropdown();
super.initState();
}
void onceSetupDropdown() async {
_userSelection = await db.getUserModelData();
_screenStage = "loaded"; // <-- set "loaded" to display DropdownButton
setState(() {}); // <-- trigger flutter to re-execute "build" method
}
这对我们来说是强制性的,不要在内部构建方法中初始化。 因此,我们可以删除FutureBuilder
_screenStage == "loaded"
? DropdownButton<UserModel>( // <-- rendered at second "build"
items: _userSelection
.map((user) => DropdownMenuItem<UserModel>(
child: Text(user.name),
value: user,
))
.toList(),
onChanged: onChange,
isExpanded: true,
value: _currentUser,
hint: Text('Select User'),
)
: CircularProgressIndicator(), // <-- rendered at first "build"
结果
您可以在此Github Repo
中进行检查答案 1 :(得分:0)
在选择值发生变化时尝试使用String代替UserModel 。 字符串_currentUser;
onChanged: (String value) {
setState(() {
_currentUser = value;
});
},
答案 2 :(得分:0)
@ejabu的解释很有帮助,但我的代码似乎无法与他/她一样进行修改。
顺便说一句,加载和在小部件上调用多个initialize的想法将导致重新初始化DropdownButton,从而不会在抖动中显示所选值。
我对状态机有一个了解,然后在状态类中简单地添加了一个布尔变量isJustFinishedLoading = false。
...
StreamBuilder<QuerySnapshot>(
...
if(!snapshot.hasData){
print('loading...');
...
isJustFinishedLoading = true;
}
else
{
print('loaded');
...
if (isJustFinishedLoading)
{
// initialize the DropdownMenuItem ...
}
return DropdownButton ... onChanged ...
}
希望对您有帮助,2020年新年快乐!
答案 3 :(得分:0)
由于您使用的是FutureBuilder
,因此只需删除setState()
内的onChanged
:
onChanged: (UserModel value) {
_currentUser = value;
}