JSON API未更新Flutter中的UI



我使用FutureBuilder获取API请求。但它只构建一次,除非重新进行热建模,否则不会更新ui。我也尝试了StreamBuilder,并将future方法转换为stream。那么我该如何更新我的ui呢。拜托,我已经问过这个问题了,但没有得到答案。这是怎么回事?

型号

import 'dart:convert';
List<User> usersFromJson(String str) =>
List<User>.from(json.decode(str).map((json) => User.fromJson(json)));
String usersToJson(List<User> data) =>
json.encode(List<dynamic>.from(data.map((e) => e.toJson())));
class User {
int? id;
String? name;
String? username;
String? email;
String? role;
User({this.id, this.name, this.username, this.email, this.role});
@override
toString() => 'User: $name';
factory User.fromJson(Map<String, dynamic> json) => User(
email: json['email'],
name: json['name'],
id: json['id'],
username: json['username'],
role: json['role']);
Map<String, dynamic> toJson() =>
{"name": name, "username": username, "email": email, "role": role};
}

api调用

Future fetchUsers() async {
Uri url = Uri.parse("${BASE_URL}user");
final response = await http.get(url, headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer $TOKEN',
});
var userview = <User>[];
if (response.statusCode == 200) {
var jsonres = json.decode(response.body);
for (var res in jsonres) {
userview.add(User.fromJson(res));
}
}
return userview;
}
Future createUser(String name, String username, String email, String password,
String roles) async {
Uri url = Uri.parse("${BASE_URL}user");
final response = await http
.post(url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer $TOKEN',
},
body: jsonEncode(<String, dynamic>{
'name': name,
'email': email,
'username': username,
'password': password,
'roles': roles
}))
.then((value) => fetchUsers());
}

和我的页面

StreamBuilder(
stream: fetchUsers().asStream(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: [
PaginatedDataTable(
sortColumnIndex: sortColumnIndex,
sortAscending: isAscending,
columns: [
DataColumn(
label: const Text("Id"),
onSort: onSort),
DataColumn(
label: const Text("Name"),
onSort: onSort),
DataColumn(
label: const Text("Username"),
onSort: onSort),
DataColumn(
label: const Text("Email"),
onSort: onSort),
DataColumn(
label: const Text("Roles"),
onSort: onSort),
DataColumn(
label: const Text("Actions"),
onSort: onSort),
],
header: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
"Manage Users",
style: TextStyle(
fontSize: width * 0.04,
fontWeight: FontWeight.normal),
),
MaterialButton(
onPressed: () {
showMaterialModalBottomSheet(
context: context,
builder: (context) => SizedBox(
height: height * 0.9,
child:
BottomSheetWidget(),
),
shape:
const RoundedRectangleBorder(
borderRadius:
BorderRadius.only(
topLeft: Radius
.circular(
  15),
topRight: Radius
.circular(
  15))));
},
color: const Color.fromRGBO(
30, 119, 66, 1),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10)),
child: Text(
"Add User",
style: TextStyle(
color: Colors.white,
fontSize: width * 0.03),
),
)
],
),
source: dataSource(
snapshot.data! as List<User>))
],
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const Center(
child: CircularProgressIndicator());
})

另外,我正在使用分页数据表,这是它的代码。(与此相关(

在页面中

DataTableSource dataSource(List<User> userList) =>
MyTable(datasList: userList, context: context);

以及数据源页面,我在这里称之为createUser

class MyTable extends DataTableSource {
MyTable({required this.datasList, required this.context});
final List<User> datasList;
BuildContext context;
Widget Button(String title, Color color, String id) {
return MaterialButton(
onPressed: () {
//deleteUser(id);
//updateUser(id, title);
createUser("name2", "user2", "email2@email.com", "password", "Admin");
},
child: Text(
title,
style: const TextStyle(color: Colors.white),
),
color: color,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
);
}
@override
DataRow? getRow(int index) {
return DataRow.byIndex(index: index, cells: [
DataCell(Text(datasList[index].id.toString())),
DataCell(ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 100),
child: Text(
datasList[index].name.toString(),
overflow: TextOverflow.ellipsis,
),
)),
DataCell(ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 100),
child: Text(
datasList[index].username.toString(),
overflow: TextOverflow.ellipsis,
))),
DataCell(ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 100),
child: Text(
datasList[index].email.toString(),
overflow: TextOverflow.ellipsis,
))),
DataCell(ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 100),
child: Text(
datasList[index].role.toString(),
overflow: TextOverflow.ellipsis,
))),
DataCell(Row(
children: [
Button("Edit", Colors.lightBlue, datasList[index].id.toString()),
const SizedBox(
width: 5,
),
Button("Delete", Colors.red, datasList[index].id.toString()),
],
)),
]);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => datasList.length;
@override
int get selectedRowCount => 0;
}

StreamBuilder类

小部件重建由每次交互安排,使用State.setState,但在其他方面与流动


我看到了代码,没有发现任何问题。但对CCD_ 6有点怀疑。

正如文件所说:asStream方法:

创建一个包含此未来结果的流。

也许你可以试试这个:stream.fromFuture

在此处找到问题:https://stackoverflow.com/a/55169382/12838877由于fetch方法并不常见,所以它是返回Future值的Future方法。

Stream.fromFuture(fetchUsers)

这只是我的怀疑。希望能解决问题。因为在评论中解释太长了,所以我会把它放在的答案部分

最新更新