I’m a beginner programmer trying to create a mental health app. In Calendar screen you can press on a date and you’re forwarded to Journal Entry screen where you can select a mood in a DropdownButtonFormField
and write a journal entry in a TextFormField
. When I select a mood I get an error [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Mood' is not a subtype of type 'MoodType'
. What is the problem and how can I resolve it?
Here’s a full error log:
Restarted application in 801ms.
I/zygote (15437): Do partial code cache collection, code=61KB, data=53KB
I/zygote (15437): After code cache collection, code=61KB, data=53KB
I/zygote (15437): Increasing code cache capacity to 256KB
I/flutter (15437): Selected date: 2023-05-03 00:00:00.000
E/flutter (15437): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type ‘Mood’ is not a subtype of type ‘MoodType’
E/flutter (15437): #0 _JournalEntryScreenState.build.. (package:v1/journal_entry.dart:137:21)
E/flutter (15437): #1 State.setState (package:flutter/src/widgets/framework.dart:1133:30)
E/flutter (15437): #2 _JournalEntryScreenState.build. (package:v1/journal_entry.dart:136:19)
E/flutter (15437): #3 _DropdownButtonFormFieldState.didChange (package:flutter/src/material/dropdown.dart:1686:39)
E/flutter (15437): #4 _DropdownButtonState._handleTap. (package:flutter/src/material/dropdown.dart:1325:25)
E/flutter (15437):
E/flutter (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),
};
I can also add calendar_screen.dart and db_helper.dart if it’s needed for the reproduction of the error.
I’ve tried to refactor the code to use MoodType type instead of mood and tried implementing MoodType to the class Mood, but I feel completely stuck.
2
Answers
Your dropdown is based on
Mood
but your_selectedMood
is aMoodType
. In the onchanged you try to assign aMood
to aMoodType
. Try changingto
and I believe a similar mistake is done at the items. I think
needs to be
Your
_selectedMood
object is aMoodType
, so yourDropdownMenuItem
s values (currently a wholeMood
object frommoodMap
) should be of the same type.Changing their
value
properties like this should do the trick: