Flutter中如何在其他类的Text Widget显示API响应数据?
问题描述
已通过POST方法成功向服务器发送数据,服务器返回的响应可在控制台查看,现在需要将这些响应数据在另一个类的Text Widget中展示。
API服务类
class APIService { Future<DoctorResponseLoginModels> register( DoctorRequestLoginModels doctorLoginRequestModels) async { String url = "http://202.51.75.142:9028/api/PatientMaster/PostPatientLogin"; SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); var globalToken = sharedPreferences.getString("token"); print("$globalToken"); http.Response response = await http.post(Uri.parse(url), headers: { "Content-Type": "application/json", 'Accept': 'application/json', 'Authorization': 'Bearer $globalToken', }, body: jsonEncode(doctorLoginRequestModels)); var responseJson = json.decode(response.body.toString()); DoctorResponseLoginModels responseModel = DoctorResponseLoginModels.fromJson(responseJson); print("This is ${response.body}"); if (response.statusCode == 200) { sharedPreferences.setInt('code', response.statusCode); var StatusCode = sharedPreferences.getInt('code'); print("This contains : $StatusCode"); print(response.statusCode); return DoctorResponseLoginModels.fromJson(jsonDecode(response.body)); } else { throw Exception('Failed'); } } }
请求模型类
DoctorRequestLoginModels doctorRequestLoginModelsFromJson(String str) => DoctorRequestLoginModels.fromJson(json.decode(str)); String doctorRequestLoginModelsToJson(DoctorRequestLoginModels data) => json.encode(data.toJson()); class DoctorRequestLoginModels { DoctorRequestLoginModels({ required this.code, required this.username, required this.password, }); String code; String username; String password; factory DoctorRequestLoginModels.fromJson(Map<String, dynamic> json) => DoctorRequestLoginModels( code: json["code"], username: json["username"], password: json["password"], ); Map<String, dynamic> toJson() => { "code": code, "username": username, "password": password, }; }
响应模型类
DoctorResponseLoginModels doctorResponseLoginModelsFromJson(String str) => DoctorResponseLoginModels.fromJson(json.decode(str)); String doctorResponseLoginModelsToJson(DoctorResponseLoginModels data) => json.encode(data.toJson()); class DoctorResponseLoginModels { DoctorResponseLoginModels({ this.doctorId, this.nmCno, this.doctorName, this.contactNo, this.username, this.emailId, this.strEmail, this.id, this.intMobile, this.gender, this.currentAddress, this.depId, this.entryDate, this.password, this.code, this.isActive, this.hospitalName, this.department, this.deviceId, this.profile, this.token, this.role, }); int? doctorId; String? nmCno; String? doctorName; String? contactNo; dynamic? username; String? emailId; String? strEmail; int? id; String? intMobile; dynamic? gender; String? currentAddress; int? depId; String? entryDate; dynamic? password; dynamic? code; bool? isActive; dynamic? hospitalName; dynamic? department; dynamic? deviceId; String? profile; String? token; String? role; factory DoctorResponseLoginModels.fromJson(Map<String, dynamic> json) => DoctorResponseLoginModels( doctorId: json["doctorID"], nmCno: json["nmCno"], doctorName: json["doctorName"], contactNo: json["contactNo"], username: json["username"], emailId: json["emailID"], strEmail: json["strEmail"], id: json["id"], intMobile: json["intMobile"], gender: json["gender"], currentAddress: json["currentAddress"], depId: json["depId"], entryDate: json["entryDate"], password: json["password"], code: json["code"], isActive: json["isActive"], hospitalName: json["hospitalName"], department: json["department"], deviceId: json["deviceId"], profile: json["profile"], token: json["token"], role: json["role"], ); Map<String, dynamic> toJson() => { "doctorID": doctorId, "nmCno": nmCno, "doctorName": doctorName, "contactNo": contactNo, "username": username, "emailID": emailId, "strEmail": strEmail, "id": id, "intMobile": intMobile, "gender": gender, "currentAddress": currentAddress, "depId": depId, "entryDate": entryDate, "password": password, "code": code, "isActive": isActive, "hospitalName": hospitalName, "department": department, "deviceId": deviceId, "profile": profile, "token": token, "role": role, }; }
尝试的FutureBuilder展示代码
return Scaffold( backgroundColor: const Color.fromRGBO(249, 249, 249, 10), body: Column( children: [ Expanded( child: Container( height: 150.0, width: 150.0, color: Colors.grey.shade100, child: FutureBuilder<DoctorResponseLoginModels>( future: APIService().register(DoctorRequestLoginModels( code: "code", username: "username", password: "password")), builder: (context, snapshot) { switch (snapshot.connectionState) { case ConnectionState.waiting: return Text('Loading....'); default: if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { DoctorResponseLoginModels data = snapshot.data!; return Column( children: [ Text(data.doctorName!), ], ); } } }, ), )), ], ));
控制台返回的响应数据
{"doctorID":1,"nmCno":"001","doctorName":"Dr. John Doe","contactNo":"1234567890","username":"john","emailID":"john@example.com","strEmail":"john@example.com","id":1,"intMobile":"1234567890","gender":"Male","currentAddress":"123 Street","depId":1,"entryDate":"2024-01-01","password":null,"code":null,"isActive":true,"hospitalName":"City Hospital","department":"Cardiology","deviceId":null,"profile":"profile.jpg","token":"abc123","role":"Doctor"}
解决方案
1. 修复FutureBuilder重复请求问题
当前代码直接在FutureBuilder的future参数中调用API方法,会导致Widget重建时重复发起请求。建议在initState中提前初始化Future:
class DoctorInfoPage extends StatefulWidget { const DoctorInfoPage({super.key}); @override State<DoctorInfoPage> createState() => _DoctorInfoPageState(); } class _DoctorInfoPageState extends State<DoctorInfoPage> { late Future<DoctorResponseLoginModels> _loginFuture; @override void initState() { super.initState(); // 替换为实际的请求参数 _loginFuture = APIService().register(DoctorRequestLoginModels( code: "your_code", username: "your_username", password: "your_password")); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color.fromRGBO(249, 249, 249, 10), body: Column( children: [ Expanded( child: Container( height: 150.0, width: 150.0, color: Colors.grey.shade100, child: FutureBuilder<DoctorResponseLoginModels>( future: _loginFuture, builder: (context, snapshot) { switch (snapshot.connectionState) { case ConnectionState.waiting: return const Center(child: Text('加载中....')); case ConnectionState.done: if (snapshot.hasError) { return Center(child: Text('错误: ${snapshot.error}')); } else if (snapshot.hasData) { final data = snapshot.data!; return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('医生姓名: ${data.doctorName ?? "无数据"}'), Text('联系电话: ${data.contactNo ?? "无数据"}'), Text('邮箱: ${data.emailId ?? "无数据"}'), Text('角色: ${data.role ?? "无数据"}'), ], ); } else { return const Center(child: Text('无返回数据')); } default: return const Center(child: Text('请求中...')); } }, ), ), ), ], ), ); } }
2. 处理空值安全
响应模型的字段都是可空类型,直接用!强制解包会引发空指针异常,建议用??设置默认值。
3. 跨类传递数据的其他方式
如果需要在多个类间共享数据,可选择两种方式:
- 构造函数传递:将获取到的
DoctorResponseLoginModels实例通过构造函数传给目标Widget
class DoctorDisplayWidget extends StatelessWidget { final DoctorResponseLoginModels doctorData; const DoctorDisplayWidget({super.key, required this.doctorData}); @override Widget build(BuildContext context) { return Column( children: [ Text('姓名: ${doctorData.doctorName ?? "未知"}'), Text('所属科室: ${doctorData.department ?? "未知"}'), ], ); } } // 在获取数据后跳转传递 // 示例:在FutureBuilder的done分支中 Navigator.push( context, MaterialPageRoute( builder: (context) => DoctorDisplayWidget(doctorData: snapshot.data!), ), );
- 状态管理工具:使用Provider、Riverpod等全局状态管理工具,将数据存入全局状态,在任意Widget中读取。
内容的提问来源于stack exchange,提问作者Mr.Robot
相关产品推荐
相关产品推荐

