Flutter中GetConnect/GetX未调用后端且返回null对象问题
问题描述
使用GetX 4.6.5实现登录接口调用,按以下步骤实现后,控制台输出flutter: {jwt: null},且本地localhost:1337服务未被调用:
- 定义Provider类:
class CredentialsProvider extends GetConnect implements GetxService { @override void onInit() { httpClient.defaultDecoder = (val) => Auth.fromJson(val as Map<String, dynamic>); httpClient.baseUrl = 'http://localhost:1337/api/'; super.onInit(); } Future<Response<dynamic>> postCredentials(Credentials credentials) async { return await post('auth/local', credentials); } }
- 在Binding类中添加依赖:
class LoginBinding extends Bindings { @override void dependencies() { Get.lazyPut(() => CredentialsProvider()); Get.lazyPut(() => LoginController()); } }
- 注册LoginView路由:
GetPage( name: "/login", page: () => const LoginView(), binding: LoginBinding(), )
- 在控制器中添加Provider:
class LoginController extends GetxController { final provider = Get.put(CredentialsProvider()); //... }
- LoginView使用该控制器:
class LoginView extends GetView<LoginController> {...}
- 在LoginView的MaterialButton的onPressed中调用接口并打印结果:
onPressed: () { var c = Credentials( identifier: controller.emailController.text, password: controller.passwordController.text); controller.provider.postCredentials(c).then((value) { var auth = value.body as Auth; print(auth.toJson()); }); },
- 通过GetX CLI生成Auth模型:
class Auth { String? jwt; User? user; Auth({this.jwt, this.user}); Auth.fromJson(Map<String, dynamic> json) { jwt = json['jwt']; user = json['user'] != null ? User?.fromJson(json['user']) : null; } Map<String, dynamic> toJson() { final data = <String, dynamic>{}; data['jwt'] = jwt; if (user != null) { data['user'] = user?.toJson(); } return data; } } class User { int? id; String? username; String? email; String? provider; bool? confirmed; bool? blocked; String? createdAt; String? updatedAt; User( {this.id, this.username, this.email, this.provider, this.confirmed, this.blocked, this.createdAt, this.updatedAt}); User.fromJson(Map<String, dynamic> json) { id = json['id']; username = json['username']; email = json['email']; provider = json['provider']; confirmed = json['confirmed']; blocked = json['blocked']; createdAt = json['createdAt']; updatedAt = json['updatedAt']; } Map<String, dynamic> toJson() { final data = <String, dynamic>{}; data['id'] = id; data['username'] = username; data['email'] = email; data['provider'] = provider; data['confirmed'] = confirmed; data['blocked'] = blocked; data['createdAt'] = createdAt; data['updatedAt'] = updatedAt; return data; } }
解决方案
1. 修复重复初始化Provider的问题
在LoginBinding中已经通过Get.lazyPut注册了CredentialsProvider,但控制器里又调用Get.put创建了新实例,导致新实例的onInit未执行(baseUrl和defaultDecoder未配置),请求根本没有发送。
修改控制器代码,改用Get.find()获取已注册的实例:
class LoginController extends GetxController { final provider = Get.find<CredentialsProvider>(); //... }
2. 确保Credentials类实现toJson方法
GetConnect.post需要将请求对象序列化为JSON,若Credentials没有实现toJson,请求体为空会导致服务端无法处理,甚至请求发送失败。
补充Credentials类的序列化方法:
class Credentials { final String identifier; final String password; Credentials({required this.identifier, required this.password}); Map<String, dynamic> toJson() { return { 'identifier': identifier, 'password': password, }; } }
3. 修复Auth模型的fromJson错误
原模型中User?.fromJson的多余问号会导致无法正确解析用户数据,修改为:
user = json['user'] != null ? User.fromJson(json['user']) : null;
4. 调整本地服务地址(模拟器环境)
Android模拟器无法直接通过localhost访问电脑本地服务,需替换为10.0.2.2;iOS模拟器可保留localhost或使用127.0.0.1。
修改Provider的baseUrl:
// Android模拟器 httpClient.baseUrl = 'http://10.0.2.2:1337/api/'; // iOS模拟器 // httpClient.baseUrl = 'http://localhost:1337/api/';
5. 添加错误日志排查
在请求回调中加入错误处理,方便定位问题:
controller.provider.postCredentials(c).then((value) { if (value.hasError) { print('请求状态码:${value.statusCode}'); print('错误信息:${value.statusText}'); print('错误详情:${value.error}'); } else { var auth = value.body as Auth; print(auth.toJson()); } }).catchError((e) { print('捕获异常:$e'); });
内容的提问来源于stack exchange,提问作者Nima Mazloumi
相关产品推荐
相关产品推荐

