Flutter Sqflite切换登录状态页面时触发空值运算符错误
问题描述
尝试根据用户登录状态在登录页和首页之间切换,替换首页为其他页面时逻辑正常,热重启后能正确展示对应页面;但切回首页时,会触发“null operator used on null value”错误。
相关代码
页面切换逻辑(Testing组件)
class Testing extends StatefulWidget { const Testing({super.key}); @override State<Testing> createState() => _TestingState(); } class _TestingState extends State<Testing> { @override Widget build(BuildContext context) { return FutureBuilder( future: TodoServiceHelper().checkifLoggedIn(), builder: ((context, snapshot) { if (!snapshot.hasData) { return Container( child: Center( child: CircularProgressIndicator(), ), ); } if (snapshot.hasError) { print(snapshot.hasError); return Container( child: Center( child: CircularProgressIndicator(), ), ); } if (snapshot.data!.isNotEmpty) { print(snapshot.data); return RegisterPage(); // 返回HomePage时会触发null check错误 } else return Login(); }), ); } }
首页(HomePage组件)
class HomePage extends StatefulWidget { String? username; HomePage({this.username}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { final GlobalKey<FormState> formKey = GlobalKey(); TextEditingController termController = TextEditingController(); void clearText() { termController.clear(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( actions: <Widget>[ IconButton( onPressed: () { User loginUser = User(username: widget.username.toString(), isLoggedIn: false); TodoServiceHelper().updateUserName(loginUser); Navigator.pushReplacement( context, MaterialPageRoute( builder: (BuildContext context) => Login())); }, icon: Icon(Icons.logout), color: Colors.white, ) ], title: FutureBuilder( future: TodoServiceHelper().getTheUser(widget.username!), builder: (context, snapshot) { if (!snapshot.hasData) { return Container( child: Center( child: CircularProgressIndicator(), ), ); } return Text( 'Welcome ${snapshot.data!.username}', style: TextStyle(color: Colors.white), ); }), ), body: SingleChildScrollView( child: Column(children: [ Column( children: [ Padding( padding: const EdgeInsets.all(12.0), child: Form( key: formKey, child: Column( children: <Widget>[ TextFormField( controller: termController, decoration: InputDecoration( filled: true, fillColor: Colors.white, enabledBorder: OutlineInputBorder(), labelText: 'search todos', ), ), TextButton( onPressed: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) => ShowingSerachedTitle( userNamee: widget.username!, searchTerm: termController.text, )), ); print(termController.text); clearText(); setState(() {}); }, child: Text( 'Search', )), Divider( thickness: 3, ), ], ), ), ), ], ), Container( child: Stack(children: [ Positioned( bottom: 0, child: Text( ' done Todos', style: TextStyle(fontSize: 12), ), ), IconButton( onPressed: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) => CheckingStuff(userNamee: widget.username!)), ); setState(() {}); }, icon: Icon(Icons.filter), ), ]), ), Divider( thickness: 3, ), Container( child: TodoListWidget(name: widget.username!), height: 1000, width: 380, ) ]), ), floatingActionButton: FloatingActionButton( backgroundColor: Color.fromARGB(255, 255, 132, 0), onPressed: () async { await showDialog( barrierDismissible: false, context: context, builder: ((context) { return AddNewTodoDialogue(name: widget.username!); }), ); setState(() {}); }, child: Icon(Icons.add), ), ); } }
登录状态检查函数
Future<List<User>> checkifLoggedIn() async { final Database db = await initializeDB(); final List<Map<String, Object?>> result = await db.query( 'users', where: 'isLoggedIn = ?', whereArgs: ['1'], ); List<User> filtered = []; for (var item in result) { filtered.add(User.fromMap(item)); } return filtered; }
问题原因
错误根源是返回HomePage时没有传入username参数,而HomePage内部大量使用widget.username!这个非空断言——当username为null时,非空断言就会触发"null operator used on null value"错误。
当前返回RegisterPage时能正常运行,是因为RegisterPage没有依赖这个必填的username;但HomePage的所有核心逻辑(获取用户信息、跳转搜索页、待办列表等)都依赖widget.username,且直接用了非空断言强制解包。
修复方案
修改Testing组件中返回HomePage的代码,从登录用户列表里取出第一个用户的username传入:
if (snapshot.data!.isNotEmpty) { print(snapshot.data); // 取列表第一个用户的username传入HomePage return HomePage(username: snapshot.data!.first.username); } else { return Login(); }
额外优化(可选)
为了避免后续再出现类似问题,可以把HomePage的username改成必填参数:
class HomePage extends StatefulWidget { // 改成required且非空 final String username; HomePage({required this.username}); @override State<HomePage> createState() => _HomePageState(); }
这样编译器会在你忘记传参时直接报错,提前避免运行时错误。
内容的提问来源于stack exchange,提问作者mohitnx
相关产品推荐
相关产品推荐

