You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Provider构建笔记应用遇空白屏问题排查请求

排查Flutter Provider笔记应用空白问题

核心错误点

  • TextField赋值错误:两个TextFormField的onChanged都将值赋给了description,第一个输入框(标题)应赋值给title。
  • 实例化对象无效:每次调用GettingNotes()都会创建新实例,赋值的属性属于临时对象,无法被Provider读取。
  • 未触发Provider更新:保存数据后未调用Provider的方法添加笔记并通知UI,Provider的列表始终为空。
  • 空安全风险:直接用!强制解包可能引发空指针异常,未处理空值场景。
  • 逻辑冗余:GettingNotes类设计多余,笔记添加逻辑应直接整合到Provider内部。

修正后的代码

1. UserNotes类(修正拼写错误)

class UserNotes {
  String title;
  String description;

  UserNotes({required this.title, required this.description});
}

2. Provider类(重构核心逻辑)

import 'package:flutter/foundation.dart';
import 'UserNotes.dart';

class ProviderData extends ChangeNotifier {
  List<UserNotes> _users = [];

  List<UserNotes> get newusers => _users;

  // 添加笔记并通知UI更新
  void addNote(String title, String description) {
    _users.add(UserNotes(title: title, description: description));
    notifyListeners();
  }
}

3. UI代码(修正赋值+调用Provider)

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../Provider/Provder.dart';
import '../models/UserNotes.dart';

class Notes extends StatefulWidget {
  @override
  createState() => _Notes();
}

class _Notes extends State<Notes> {
  final _titleController = TextEditingController();
  final _descriptionController = TextEditingController();

  @override
  void dispose() {
    _titleController.dispose();
    _descriptionController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Consumer<ProviderData>(builder:
              (BuildContext context, ProviderData value, Widget? child) {
            return ListView.builder(
                itemCount: value.newusers.length,
                itemBuilder: ((context, index) {
                  return ListTile(
                    title: Text(value.newusers[index].title),
                    subtitle: Text(value.newusers[index].description),
                  );
                }));
          }),
          Align(
            alignment: Alignment.bottomCenter,
            child: Padding(
              padding: const EdgeInsets.only(bottom: 20),
              child: FloatingActionButton(
                backgroundColor: Colors.black54,
                child: const Icon(Icons.add, size: 40),
                onPressed: () => showDialog(
                  context: context,
                  builder: (BuildContext context) => AlertDialog(
                    title: const Text('NOTES INFO'),
                    content: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        TextFormField(
                          controller: _titleController,
                          decoration: const InputDecoration(
                              hintText: 'Enter notes title',
                              border: OutlineInputBorder()),
                        ),
                        const SizedBox(height: 20),
                        TextFormField(
                          controller: _descriptionController,
                          decoration: const InputDecoration(
                              hintText: 'Enter notes description',
                              border: OutlineInputBorder()),
                        ),
                      ],
                    ),
                    actions: <Widget>[
                      TextButton(
                        onPressed: () {
                          final title = _titleController.text.trim();
                          final description = _descriptionController.text.trim();
                          if (title.isNotEmpty && description.isNotEmpty) {
                            Provider.of<ProviderData>(context, listen: false)
                                .addNote(title, description);
                            _titleController.clear();
                            _descriptionController.clear();
                          }
                          Navigator.pop(context);
                        },
                        child: const Text('Save Data'),
                      ),
                      TextButton(
                          onPressed: () => Navigator.pop(context),
                          child: const Text('Cancel'))
                    ],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

额外优化点

  • 用TextEditingController替代setState跟踪输入值,代码更简洁高效。
  • 弹窗Column添加mainAxisSize: MainAxisSize.min,避免高度超出屏幕。
  • 将ListTile的leading改为subtitle,符合笔记展示的布局逻辑。
  • 添加输入值非空判断,避免创建空笔记。

内容的提问来源于stack exchange,提问作者Emmanuel Armoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 06:30:41