Flutter如何将TextEditingController取值传递到其他类并适配空安全
适配空安全的实现方案
核心解决两个问题:适配Flutter空安全语法要求,解耦设置页与API层逻辑,避免使用高耦合的GlobalKey跨组件取状态。
1. 修改api.dart代码
首先修正http请求参数类型,封装可配置的全局API地址,适配空安全校验规则:
import 'package:flutter/cupertino.dart'; import 'package:futurebuilder_example/model/devices.dart'; import 'package:http/http.dart' as http; // 封装全局API配置类,明确变量可空/非空状态 class ApiConfig { static String? _baseUrl; // 对外暴露设置地址的方法 static void setBaseUrl(String inputUrl) => _baseUrl = inputUrl.trim(); // 对外暴露获取地址的方法,提前做空判断避免空异常 static String get baseUrl { if (_baseUrl == null) throw Exception('请先在设置页配置API端点地址'); return _baseUrl!; } } class DeviceApi { static Future<List<Devices>> getDevices() async { // 新版http库要求传入Uri类型参数,需转换字符串地址 final requestUri = Uri.parse(ApiConfig.baseUrl); final response = await http.get(requestUri); print(response.statusCode); if (response.statusCode == 200) { return devicesFromJson(response.body); } else { throw Exception('Failed to load devices'); } } }
2. 修改settings_page.dart代码
增加提交保存逻辑,用户输入完成后直接更新全局API配置即可:
import 'package:flutter/material.dart'; import 'package:futurebuilder_example/api.dart'; class SettingsPage extends StatefulWidget { @override SettingsPageState createState() { return SettingsPageState(); } } class SettingsPageState extends State<SettingsPage> { // 控制器初始化默认值,明确为非空类型 final myController = TextEditingController(text: "https://默认API地址.com"); @override void dispose() { myController.dispose(); super.dispose(); } // 保存输入的API地址 void _saveApiUrl() { final inputUrl = myController.text.trim(); // 可自定义地址格式校验规则 if (inputUrl.startsWith(RegExp(r'https?://'))) { ApiConfig.setBaseUrl(inputUrl); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('API地址保存成功')) ); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请输入合法的http/https格式地址')) ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('API地址配置'), actions: [ // 右上角保存按钮 IconButton( onPressed: _saveApiUrl, icon: const Icon(Icons.save) ) ], ), body: Padding( padding: const EdgeInsets.all(16.0), child: TextField( controller: myController, keyboardType: TextInputType.url, decoration: const InputDecoration( labelText: '请输入API端点地址', hintText: 'https://example.com/api/devices' ), ), ), ); } }
可选优化:持久化存储配置
如果需要APP重启后配置不丢失,可引入shared_preferences依赖包,在ApiConfig的setBaseUrl方法和baseUrlget方法中增加本地存储的读写逻辑即可,上层调用逻辑无需改动。
注意事项
- 不要在页面State内定义GlobalKey供外部调用,该写法严重违反组件封装原则,后续维护成本极高
- 所有变量需提前明确可空/非空属性,使用可空变量时提前做空判断,或在确认非空场景下用
!做非空断言 - 新版http库的请求方法需传入Uri类型参数,字符串地址需通过
Uri.parse()转换后再使用
内容的提问来源于stack exchange,提问作者ggk
相关产品推荐
相关产品推荐

