我是一名尝试创建心理健康应用程序的初级程序员。在日历屏幕中,您可以按一个日期,然后您将被转发到日记条目屏幕,您可以在其中选择
DropdownButtonFormField
的心情并在 TextFormField
中写日记条目。当我选择一种心情时,我得到一个错误[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Mood' is not a subtype of type 'MoodType'
。问题是什么,我该如何解决?
这是完整的错误日志: 在 801 毫秒后重新启动应用程序。 I/zygote (15437): 做部分代码缓存收集,代码=61KB,数据=53KB I/zygote (15437): 代码缓存收集后,代码=61KB,数据=53KB I/zygote (15437):将代码缓存容量增加到 256KB I/flutter (15437): 选择日期:2023-05-03 00:00:00.000 E/flutter (15437): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] 未处理的异常:类型 'Mood' 不是类型 'MoodType' 的子类型 E/颤振 (15437): #0 _JournalEntryScreenState.build.. (package:v1/journal_entry.dart:137:21) E/flutter (15437): #1 State.setState (包:flutter/src/widgets/framework.dart:1133:30) E/flutter (15437):#2 _JournalEntryScreenState.build。 (包:v1/journal_entry.dart:136:19) E/flutter (15437): #3 _DropdownButtonFormFieldState.didChange (包:flutter/src/material/dropdown.dart:1686:39) E/flutter (15437):#4 _DropdownButtonState._handleTap。 (包:flutter/src/material/dropdown.dart:1325:25) E/颤动(15437): E/颤动(15437):
**journal_entry.dart:**
import 'package:flutter/material.dart';
import 'db_helper.dart';
import 'event_interface.dart';
import 'package:intl/intl.dart';
import 'mood_type.dart';
class JournalEntry extends StatefulWidget implements EventInterface {
final int id;
@required final DateTime date;
final MoodType mood;
final String entry;
JournalEntry({this.id, @required this.date, @required this.mood, this.entry});
@override
DateTime get eventDate => date;
Map<String, dynamic> toMap() {
return {
'id': id,
'date': date?.millisecondsSinceEpoch ?? 0,
'mood': mood?.index ?? 0,
'entry': entry,
};
}
static JournalEntry fromMap(Map<String, dynamic> map) {
return JournalEntry(
id: map['id'],
date: DateTime.fromMillisecondsSinceEpoch(map['date']),
mood: MoodType.values[map['mood']],
entry: map['entry'],
);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is JournalEntry &&
runtimeType == other.runtimeType &&
id == other.id &&
date == other.date &&
mood == other.mood &&
entry == other.entry;
@override
int get hashCode =>
id.hashCode ^ date.hashCode ^ mood.hashCode ^ entry.hashCode;
@override
_JournalEntryState createState() => _JournalEntryState();
}
class _JournalEntryState extends State<JournalEntry> {
@override
Widget build(BuildContext context) {
throw UnimplementedError();
}
}
class JournalEntryScreen extends StatefulWidget {
final DateTime selectedDate;
JournalEntryScreen({Key key, this.selectedDate}) : super(key: key);
@override
_JournalEntryScreenState createState() => _JournalEntryScreenState();
}
class _JournalEntryScreenState extends State<JournalEntryScreen> {
DateTime _selectedDate;
final _formKey = GlobalKey<FormState>();
TextEditingController _journalEntryController = TextEditingController();
String _journalEntry = '';
MoodType _selectedMood;
@override
void initState() {
super.initState();
_selectedDate = widget.selectedDate ?? DateTime.now();
_getJournalEntry(_selectedDate);
}
void _getJournalEntry(DateTime date) async {
DatabaseHelper databaseHelper = DatabaseHelper.instance;
List<JournalEntry> entries =
await databaseHelper.getJournalEntryByDate(date);
if (entries != null && entries.isNotEmpty) {
JournalEntry entry = entries.first;
print('Retrieved journal entry for date: ${entry.date}');
setState(() {
_journalEntry = entry.entry;
_selectedDate = entry.date;
_selectedMood = entry.mood;
print('Selected date updated to: $_selectedDate');
});
print('Set state for date: $_selectedDate and journal entry: $_journalEntry');
_journalEntryController.text = _journalEntry;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Journal Entry'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
DateFormat.yMMMMd().format(widget.selectedDate ?? DateTime.now()),
style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
SizedBox(height: 16.0),
DropdownButtonFormField(
value: _selectedMood,
hint: Text('Select a mood'),
items: moodMap.values
.map((mood) => DropdownMenuItem(
value: mood,
child: Text(mood.name),
))
.toList(),
onChanged: (value) {
setState(() {
_selectedMood = value;
});
},
validator: (value) {
if (value == null) {
return 'Please select a mood';
}
return null;
},
),
TextFormField(
controller: _journalEntryController,
decoration: InputDecoration(
hintText: 'Write your journal entry here',
border: OutlineInputBorder(),
),
maxLines: null,
onChanged: (value) {
setState(() {
_journalEntry = value;
});
},
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
SizedBox(height: 16.0),
ElevatedButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
JournalEntry entry = JournalEntry(
date: widget.selectedDate,
mood: _selectedMood,
entry: _journalEntry,
);
DatabaseHelper databaseHelper = DatabaseHelper.instance;
int id = await databaseHelper.insertJournalEntry(entry);
Navigator.pop(context, true);
}
},
child: Text('Save'),
),
],
),
),
),
);
}
}
**mood_type.dart:**
import 'dart:ui';
import 'package:flutter/material.dart';
enum MoodType {
veryHappy,
happy,
neutral,
sad,
verySad
}
class Mood {
final String name;
final Color color;
final MoodType type;
Mood({this.name, this.color, this.type});
}
final moodMap = {
MoodType.veryHappy: Mood(name: 'Very Happy', color: Colors.green, type: MoodType.veryHappy),
MoodType.happy: Mood(name: 'Happy', color: Colors.lightGreen, type: MoodType.happy),
MoodType.neutral: Mood(name: 'Neutral', color: Colors.grey, type: MoodType.neutral),
MoodType.sad: Mood(name: 'Sad', color: Colors.blue, type: MoodType.sad),
MoodType.verySad: Mood(name: 'Very Sad', color: Colors.black87, type: MoodType.verySad),
};
如果需要重现错误,我还可以添加 calendar_screen.dart 和 db_helper.dart。
我尝试重构代码以使用 MoodType 类型而不是心情,并尝试将 MoodType 实现到 Mood 类,但我觉得完全卡住了。
您的下拉列表基于
Mood
,但您的_selectedMood
是MoodType
。在 onchanged 中,您尝试将 Mood
分配给 MoodType
。尝试改变
onChanged: (value) {
setState(() {
_selectedMood = value;
});
},
到
onChanged: (value) {
setState(() {
_selectedMood = value.type;
});
},
我相信在物品上也犯了类似的错误。我觉得
items: moodMap.values
.map((mood) => DropdownMenuItem(
value: mood,
child: Text(mood.name),
))
需要
items: moodMap.values
.map((mood) => DropdownMenuItem(
value: mood.type,
child: Text(mood.name),
))
你的
_selectedMood
对象是一个MoodType
,所以你的DropdownMenuItem
s值(当前来自Mood
的整个moodMap
对象)应该是相同的类型。
像这样改变他们的
value
属性应该可以解决问题:
DropdownButtonFormField(
value: _selectedMood,
hint: Text('Select a mood'),
items: moodMap.values
.map((mood) => DropdownMenuItem(
value: mood.type,
child: Text(mood.name),
))
.toList(),
...