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

Flutter复用页面实现联系人增改时传参报错求助

问题解析与修复方案

问题根源

崩溃的核心原因是:点击新增按钮跳转页面时,没有传递arguments参数,但代码里用as Map<dynamic, dynamic>强制将null转换为Map类型,Flutter不允许这种强转,因此抛出type 'Null' is not a subtype of type 'Map<dynamic, dynamic>'错误。


修复步骤

1. 改用可空类型接收参数

先把参数接收改为可空Map,避免强转崩溃:

final routeArgs = ModalRoute.of(context)?.settings?.arguments as Map<dynamic, dynamic>?;

2. 区分新增/编辑模式

通过routeArgs是否为null判断当前模式,并初始化表单数据。建议用TextEditingController管理输入框内容,比直接用initialValue更灵活:

// 在State类中定义控制器和模式变量
final _nameController = TextEditingController();
late bool isNewContact;
Map<dynamic, dynamic>? routeArgs;

@override
void initState() {
  super.initState();
  routeArgs = ModalRoute.of(context)?.settings?.arguments as Map<dynamic, dynamic>?;
  isNewContact = routeArgs == null;
  
  // 编辑模式下填充已有数据
  if (!isNewContact) {
    category = routeArgs!['category'] ?? 'Intern';
    _nameController.text = routeArgs!['name'] ?? '';
    // 其他字段(邮箱、电话等)同理初始化
  }
}

3. 修复表单字段与UI逻辑

把TextFormField改为绑定控制器,同时根据模式调整页面标题、按钮显示:

// 页面标题
appBar: AppBar(
  title: isNewContact ? const Text('New Contact') : const Text('Edit Contact'),
),

// 表单输入框示例
TextFormField(
  controller: _nameController,
  decoration: const InputDecoration(labelText: 'Name'),
  validator: (value) {
    if (value == null || value.isEmpty) {
      return 'Please enter a name';
    }
    return null;
  },
),

// 按钮区域:编辑模式才显示Edit按钮
Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    TextButton(
      onPressed: _saveContact,
      child: const Text('Save'),
    ),
    if (!isNewContact)
      TextButton(
        onPressed: () {
          // 可添加编辑状态切换逻辑(比如解锁表单)
        },
        child: const Text('Edit'))
  ],
)

4. 完善保存逻辑

根据模式调用Firestore的新增或更新方法,注意编辑时需要文档ID(列表页跳转时要传递文档ID):

void _saveContact() {
  if (_formKey.currentState!.validate()) {
    final contact = Contact(
      name: _nameController.text,
      category: category,
      // 补充其他字段
    );
    
    if (isNewContact) {
      firestoreService.addContact(contact);
    } else {
      final docId = routeArgs!['docId']; // 从参数获取文档ID
      firestoreService.updateContact(docId, contact);
    }
    Navigator.pop(context);
  }
}

5. 列表页补充文档ID传递

跳转编辑页时,把Firestore文档的ID也加入参数:

// 列表页中修改data的构造
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
data['docId'] = document.id; // 新增这行,传递文档ID

修改后的完整AddContactScreen代码

import 'package:flutter/material.dart';
import '../../services/firestore_service.dart';
import '../../models/contacts/contact.dart';
import '../../utils/helper_widgets.dart';

class AddContactScreen extends StatefulWidget {
  AddContactScreen({Key? key}) : super(key: key);

  static const routeName = '/Add-contact-screen';

  @override
  State<AddContactScreen> createState() => _AddContactScreenState();
}

class _AddContactScreenState extends State<AddContactScreen> {
  String category = 'Intern';
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final firestoreService = FirestoreService();
  final _nameController = TextEditingController();
  late bool isNewContact;
  Map<dynamic, dynamic>? routeArgs;

  @override
  void initState() {
    super.initState();
    routeArgs = ModalRoute.of(context)?.settings?.arguments as Map<dynamic, dynamic>?;
    isNewContact = routeArgs == null;
    
    if (!isNewContact) {
      category = routeArgs!['category'] ?? 'Intern';
      _nameController.text = routeArgs!['name'] ?? '';
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: isNewContact ? const Text('New Contact') : const Text('Edit Contact'),
      ),
      body: SingleChildScrollView(
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              addVerticalSpace(10),
              DropdownButton(
                value: category,
                icon: const Icon(Icons.keyboard_arrow_down),
                items: dropdownItems,
                onChanged: (String? newValue) {
                  setState(() {
                    category = newValue!;
                  });
                },
              ),
              TextFormField(
                controller: _nameController,
                decoration: const InputDecoration(labelText: 'Name'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter a name';
                  }
                  return null;
                },
              ),
              // 其他表单字段(邮箱、电话等)同理实现
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  TextButton(
                    onPressed: _saveContact,
                    child: const Text('Save'),
                  ),
                  if (!isNewContact)
                    TextButton(
                      onPressed: () {
                        // 编辑状态切换逻辑
                      },
                      child: const Text('Edit'))
                ],
              )
            ],
          ),
        ),
      ),
    );
  }

  void _saveContact() {
    if (_formKey.currentState!.validate()) {
      final contact = Contact(
        name: _nameController.text,
        category: category,
        // 补充其他字段
      );
      
      if (isNewContact) {
        firestoreService.addContact(contact);
      } else {
        final docId = routeArgs!['docId'];
        firestoreService.updateContact(docId, contact);
      }
      Navigator.pop(context);
    }
  }

  @override
  void dispose() {
    _nameController.dispose();
    super.dispose();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:30:42