Flutter FutureBuilder 快照为空,但 Future 做 return 数据
Flutter FutureBuilder Snapshot is null but Future Does return data
在使用Flutter 为Kanboard 开发一个新的应用程序客户端时,我遇到了以下问题。我有一个 FutureBuilder,它应该 return 一个带有项目的 select 下拉菜单,但是由于某种原因,快照数据为空,尽管 Future 方法确实解析并且在 return 上有数据。
完整的 page.dart 代码在这里:https://pastebin.com/J48nxsdZ
出现问题的块如下:
Widget _columnSelect() {
return FutureBuilder(
future: columnProvider.getColumns(task.projectId),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<DropdownMenuItem<String>> columnList = [];
if (snapshot.hasData) {
columnList.add(DropdownMenuItem<String>(
child: Text('Select Column'), value: 0.toString()));
_columns = snapshot.data;
} else {
columnList.add(DropdownMenuItem<String>(
child: Text('Loading..'), value: 0.toString()));
}
_columns.forEach((column) {
columnList.add(DropdownMenuItem<String>(
child: Container(
child: Text(
column.title,
),
),
value: column.id.toString()));
});
return Container(
// margin: EdgeInsets.only(left: 40.0),
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: DropdownButtonFormField(
icon: Padding(
padding: const EdgeInsets.only(right: 12),
child: Icon(Icons.view_column, color: Colors.blue),
),
items: columnList,
value: _columnId,
decoration: InputDecoration(helperText: 'Optional'),
onChanged: (newValue) {
_columnId = newValue;
},
),
);
},
);
}
这是用于用户下拉列表的相同形式的小部件的副本 select。原始小部件(在同一页面中)如下:
Widget _ownerSelect() {
return FutureBuilder(
future: userProvider.getUsers(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<DropdownMenuItem<String>> usernameList = [];
if (snapshot.hasData) {
usernameList.add(DropdownMenuItem<String>(
child: Text('Select Owner'), value: 0.toString()));
_users = snapshot.data;
} else {
usernameList.add(DropdownMenuItem<String>(
child: Text('Loading..'), value: 0.toString()));
}
_users.forEach((user) {
usernameList.add(DropdownMenuItem<String>(
child: Container(
child: Text(
user.name,
),
),
value: user.id.toString()));
});
return Container(
// margin: EdgeInsets.only(left: 40.0),
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: DropdownButtonFormField(
icon: Padding(
padding: const EdgeInsets.only(right: 12),
child: Icon(Icons.person, color: Colors.blue),
),
items: usernameList,
value: _ownerId,
decoration: InputDecoration(helperText: 'Optional'),
onChanged: (newValue) {
_ownerId = newValue;
},
),
);
},
);
}
出于某种原因,“_columnSelect”AsyncSnapshot 始终为 null,即使 Future 方法工作正常也是如此:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:kanboard/src/models/column_model.dart';
import 'package:kanboard/src/preferences/user_preferences.dart';
class ColumnProvider {
final _prefs = new UserPreferences();
Future<List<ColumnModel>> getColumns(projectId) async {
final Map<String, dynamic> parameters = {
"jsonrpc": "2.0",
"method": "getColumns",
"id": 887036325,
"params": {"project_id": projectId}
};
final credentials = "${_prefs.username}:${_prefs.password}";
Codec<String, String> stringToBase64 = utf8.fuse(base64);
String encoded = stringToBase64.encode(credentials);
final resp = await http.post(
Uri.parse(_prefs.endpoint),
headers: <String, String>{"Authorization": "Basic $encoded"},
body: json.encode(parameters),
);
final decodedData = json.decode(utf8.decode(resp.bodyBytes));
final List<ColumnModel> columns = [];
final List<dynamic> results = decodedData['result'];
if (decodedData == null) return [];
results.forEach((column) {
final columnTemp = ColumnModel.fromJson(column);
columns.add(columnTemp);
});
print(columns);
return columns;
}
}
“打印(列)”的输出returns:
I/flutter ( 9486): [Instance of 'ColumnModel', Instance of 'ColumnModel', Instance of 'ColumnModel', Instance of 'ColumnModel']
我不知道我在这里错过了什么。该表单有 2 个用户下拉列表 select(使用原始的 FutureBuilder Widget),效果很好。 Future Builder 的列小部件是 snapshot.data.
中存在“空”问题的小部件
提前感谢您的宝贵时间和对此的支持!
我刚找到问题所在:
在表单页面(新任务页面)中,columnProvider.getColumns(task.projectId)) 没有执行,因为“task.projectId”参数是一个字符串,但是 API 需要一个整数。
我很困惑,因为上一页(包含所有任务的项目页面)正在调用该方法,而 getColumn 的参数确实是一个整数:int.parse(projectId)。
如果此特定调用“getColumns”的 ID 参数不是 INT(出于某种原因),看板 API 不会 return 错误代码。
当然,Flutter(或 Dart)正在等待 http.post 永远不会到达的响应。当比较两个页面的两个调用时,我注意到了差异。
因此,总而言之,我在 getColumn 定义中指定了 int 数据类型参数以避免混淆:
Future<List<ColumnModel>> getColumns(int projectId) async {
此致!
在使用Flutter 为Kanboard 开发一个新的应用程序客户端时,我遇到了以下问题。我有一个 FutureBuilder,它应该 return 一个带有项目的 select 下拉菜单,但是由于某种原因,快照数据为空,尽管 Future 方法确实解析并且在 return 上有数据。
完整的 page.dart 代码在这里:https://pastebin.com/J48nxsdZ
出现问题的块如下:
Widget _columnSelect() {
return FutureBuilder(
future: columnProvider.getColumns(task.projectId),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<DropdownMenuItem<String>> columnList = [];
if (snapshot.hasData) {
columnList.add(DropdownMenuItem<String>(
child: Text('Select Column'), value: 0.toString()));
_columns = snapshot.data;
} else {
columnList.add(DropdownMenuItem<String>(
child: Text('Loading..'), value: 0.toString()));
}
_columns.forEach((column) {
columnList.add(DropdownMenuItem<String>(
child: Container(
child: Text(
column.title,
),
),
value: column.id.toString()));
});
return Container(
// margin: EdgeInsets.only(left: 40.0),
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: DropdownButtonFormField(
icon: Padding(
padding: const EdgeInsets.only(right: 12),
child: Icon(Icons.view_column, color: Colors.blue),
),
items: columnList,
value: _columnId,
decoration: InputDecoration(helperText: 'Optional'),
onChanged: (newValue) {
_columnId = newValue;
},
),
);
},
);
}
这是用于用户下拉列表的相同形式的小部件的副本 select。原始小部件(在同一页面中)如下:
Widget _ownerSelect() {
return FutureBuilder(
future: userProvider.getUsers(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<DropdownMenuItem<String>> usernameList = [];
if (snapshot.hasData) {
usernameList.add(DropdownMenuItem<String>(
child: Text('Select Owner'), value: 0.toString()));
_users = snapshot.data;
} else {
usernameList.add(DropdownMenuItem<String>(
child: Text('Loading..'), value: 0.toString()));
}
_users.forEach((user) {
usernameList.add(DropdownMenuItem<String>(
child: Container(
child: Text(
user.name,
),
),
value: user.id.toString()));
});
return Container(
// margin: EdgeInsets.only(left: 40.0),
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: DropdownButtonFormField(
icon: Padding(
padding: const EdgeInsets.only(right: 12),
child: Icon(Icons.person, color: Colors.blue),
),
items: usernameList,
value: _ownerId,
decoration: InputDecoration(helperText: 'Optional'),
onChanged: (newValue) {
_ownerId = newValue;
},
),
);
},
);
}
出于某种原因,“_columnSelect”AsyncSnapshot 始终为 null,即使 Future 方法工作正常也是如此:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:kanboard/src/models/column_model.dart';
import 'package:kanboard/src/preferences/user_preferences.dart';
class ColumnProvider {
final _prefs = new UserPreferences();
Future<List<ColumnModel>> getColumns(projectId) async {
final Map<String, dynamic> parameters = {
"jsonrpc": "2.0",
"method": "getColumns",
"id": 887036325,
"params": {"project_id": projectId}
};
final credentials = "${_prefs.username}:${_prefs.password}";
Codec<String, String> stringToBase64 = utf8.fuse(base64);
String encoded = stringToBase64.encode(credentials);
final resp = await http.post(
Uri.parse(_prefs.endpoint),
headers: <String, String>{"Authorization": "Basic $encoded"},
body: json.encode(parameters),
);
final decodedData = json.decode(utf8.decode(resp.bodyBytes));
final List<ColumnModel> columns = [];
final List<dynamic> results = decodedData['result'];
if (decodedData == null) return [];
results.forEach((column) {
final columnTemp = ColumnModel.fromJson(column);
columns.add(columnTemp);
});
print(columns);
return columns;
}
}
“打印(列)”的输出returns:
I/flutter ( 9486): [Instance of 'ColumnModel', Instance of 'ColumnModel', Instance of 'ColumnModel', Instance of 'ColumnModel']
我不知道我在这里错过了什么。该表单有 2 个用户下拉列表 select(使用原始的 FutureBuilder Widget),效果很好。 Future Builder 的列小部件是 snapshot.data.
中存在“空”问题的小部件提前感谢您的宝贵时间和对此的支持!
我刚找到问题所在:
在表单页面(新任务页面)中,columnProvider.getColumns(task.projectId)) 没有执行,因为“task.projectId”参数是一个字符串,但是 API 需要一个整数。
我很困惑,因为上一页(包含所有任务的项目页面)正在调用该方法,而 getColumn 的参数确实是一个整数:int.parse(projectId)。
如果此特定调用“getColumns”的 ID 参数不是 INT(出于某种原因),看板 API 不会 return 错误代码。
当然,Flutter(或 Dart)正在等待 http.post 永远不会到达的响应。当比较两个页面的两个调用时,我注意到了差异。
因此,总而言之,我在 getColumn 定义中指定了 int 数据类型参数以避免混淆:
Future<List<ColumnModel>> getColumns(int projectId) async {
此致!