메모를 저장하는 형태의 어플을 만들었습니다.
Event를 활용하여 입력된 값을 저장하는 기능을 추가하려고 합니다.
part 'add_edit_note_ui_event.freezed.dart';
abstract class AddEditNoteUiEvent with _$AddEditNoteUiEvent {
const factory AddEditNoteUiEvent.saveNote() = SaveNote;
const factory AddEditNoteUiEvent.showSnackBar(String message) = ShowSnackBar;
}
final _eventController = StreamController<AddEditNoteUiEvent>.broadcast();
Stream<AddEditNoteUiEvent> get eventStream => _eventController.stream;
AddEditNoteViewModel(this.repository);
Future<void> _saveNote(int? id, String title, String content) async {
if (title.isEmpty || content.isEmpty) {
_eventController.add(const AddEditNoteUiEvent.showSnackBar('제목이나 내용이 비어 있습니다'));
return;
}
if (id == null) {
await repository.insertNote(
Note(
title: title,
content: content,
color: _color,
timestamp: DateTime.now().millisecondsSinceEpoch),
);
}
_eventController.add(const AddEditNoteUiEvent.saveNote());
}
Stream.listen을 계속하면 메모리 활용에 좋지 않은 방법입니다.
- 해결방법
- StreamSubscription타입의 _streamSubscription 변수 추가
- _streamSubscription = viewModel.eventStream.listen((event)
- dispose()에 _streamSubscription?.cancel();를 추가
- 여러 메모를 저장할 때 다시 listen 하지 않는 오류의 해결 방법
ViewModel의 StreamController에 broadcast 추가
여러 번 listen을 할 수 있는 형태로 만듭니다.
final _eventController = StreamController.broadcast();
StreamSubscription? _streamSubscription;
void initState() {
super.initState();
if (widget.note != null) {
_titleController.text = widget.note!.title;
_contentController.text = widget.note!.content;
}
Future.microtask(() {
final viewModel = context.read<AddEditNoteViewModel>();
_streamSubscription = viewModel.eventStream.listen((event) {
event.when(
saveNote: () {
Navigator.pop(context, true);
},
showSnackBar: (String message) {
final snackBar = SnackBar(content: Text(message));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
);
});
});
}
void dispose() {
_streamSubscription?.cancel();
_titleController.dispose();
_contentController.dispose();
super.dispose();
}
//AddEditNoteScreen
Navigator.pop(context, true);
//NotesScreen
bool? isSaved = await Navigator.push
floatingActionButton: FloatingActionButton(
onPressed: () async {
bool? isSaved = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AddEditNoteScreen()),
);
if (isSaved != null && isSaved) {
viewModel.onEvent(const NotesEvent.loadNotes());
}
},