가을기 Workspace

[플러터] 15일차 - 노트를 데이터베이스로 저장하기 본문

개발/개인앱

[플러터] 15일차 - 노트를 데이터베이스로 저장하기

가을기_ 2021. 7. 17. 01:49

 

 

data/note_manger.dart 를 데이터베이스를 쓰는 코드로 싹 다 바꾼다.

import 'dart:ui';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

import 'note.dart';

class NoteManager {
  static const _databaseName = 'notes.db';

  static const _databaseVersion = 1;

  Database? _database;

  List<Note> _notes = [];

  Future<void> addNote(Note note) async {
    Database db = await _getDatabase();
    db.insert(Note.tableName, note.toRow());
  }

  Future<void> deleteNote(int id) async {
    Database db = await _getDatabase();
    db.delete(Note.tableName, where: '${Note.columnId} = ?', whereArgs: [id]);
  }

  Future<Note> getNote(int id) async {
    Database db = await _getDatabase();
    List<Map<String, dynamic>> rows = await db.query(
      Note.tableName,
      where: '${Note.columnId} = ?',
      whereArgs: [id],
    );
    return Note.fromRow(rows.single);
  }

  Future<List<Note>> listNotes() async {
    Database db = await _getDatabase();
    List<Map<String, dynamic>> rows = await db.query(Note.tableName);

    return rows.map((row) => Note.fromRow(row)).toList();
  }

  Future<void> updateNote(int id, String body,
      {String title = '', Color? color}) async {
    Database db = await _getDatabase();
    db.update(
        Note.tableName,
        Note(
          body,
          title: title,
          color: color!,
        ).toRow(),
        where: '${Note.columnId} = ?',
        whereArgs: [id]);
  }

  Future<Database> _getDatabase() async {
    if (_database == null) {
      _database = await _init();
    }
    return _database!;
  }

  Future<Database> _init() async {
    String dbPath = join(await getDatabasesPath(), _databaseName);
    return openDatabase(dbPath, version: _databaseVersion,
        onCreate: (db, version) async {
      String sql = '''
      CREATE TABLE ${Note.tableName} (
        ${Note.columnId} INTEGER PRIMARY KEY AUTOINCREMENT,
        ${Note.columnTitle} TEXT,
        ${Note.columnBody} TEXT NOT NULL,
        ${Note.columnColor} INTEGER NOT NULL
      )
      ''';
      return db.execute(sql);
    });
  }
}

 

  • NotePageArgs에서 index 안쓰도록 변경
import 'package:sticky_notes/data/note.dart';

class NotePageArgs {
  late Note note;

  NotePageArgs(this.note);
}

 

이에 맞게 차근차근 NoteEditPage, NoteViewPage에서 args.index → args.note.id로 변경

noteManager().updateNote(args.note.id, body, title: title, color: color);

 

noteManager().deleteNote(args.note.id);

 

NoteListPage에서는 조금 수정이 필요하다.

먼저 NotePageArgs 생성부분에서 index 삭제

Widget _buildCard(int index, Note note) {
    return InkWell(
      onTap: () {
        Navigator.pushNamed(context, NoteViewPage.rootName,
                arguments: NotePageArgs(note))
            .then((value) {
          setState(() {});
        });
      },

 

 

 

이제 데이터베이스에서 불러오므로 FutureBuilder가 필요하다.

body: FutureBuilder(
        future: NoteManager().listNotes(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(
              child: CircularProgressIndicator(),
            );
          }

          if (snapshot.hasData) {
            List<Note> notes = snapshot.data as List<Note>;
            return GridView.builder(
                padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 16.0),
                itemCount: notes.length,
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  childAspectRatio: 1,
                ),
                itemBuilder: (context, index) {
                  return _buildCard(notes[index]);
                });
          }

 

 

그리고 노트가 저장되었을때 View에서 반영하도록 데이터베이스 접근하는 것으로 변경. 마찬가지로 FutureBuilder가 필요하다.

class _NodeViewPageState extends State<NoteViewPage> {
  @override
  Widget build(BuildContext context) {
    NotePageArgs args =
        ModalRoute.of(context)!.settings.arguments as NotePageArgs;
    // Note note = args.note;
    return FutureBuilder(
        future: noteManager().getNote(args.note.id),
        builder: (context, snapshot) {
          PreferredSizeWidget appBar;
          Widget body;

          if (snapshot.connectionState == ConnectionState.waiting) {
            appBar = AppBar();
            body = Center(
              child: CircularProgressIndicator(),
            );
          }

          if (snapshot.hasData) {
            Note note = snapshot.data as Note;

            appBar = AppBar(
                title: Text(note.title.isEmpty ? '{제목 없음}' : note.title),
                actions: [
                  IconButton(
                    icon: Icon(Icons.edit),
                    tooltip: '편집',
                    onPressed: () {
                      _edit(NotePageArgs(note));
                    },
                  ),
                  IconButton(
                    icon: Icon(Icons.delete),
                    tooltip: '삭제',
                    onPressed: () {
                      _confirmDelete(args);
                    },
                  )
                ]);

            body = SizedBox.expand(
              // 배경생, 스크롤처리를 위해
              child: Container(
                color: note.color,
                child: SingleChildScrollView(
                  padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 16.0),
                  child: Text(note.body),
                ),
              )
            );
          } else {
            appBar = AppBar();
            body = Center(
              child: Text('오류가 발생했습니다'),
            );
          }

          return Scaffold(
            appBar: appBar,
            body: body,
          );
        });

 

 

 

이제 모든게 정상작동한다.!

 

Comments