Kode lengkap aplikasi Flutter CRUD To-Do List menggunakan SQLite.

 


Berikut adalah kode lengkap aplikasi Flutter CRUD To-Do List menggunakan SQLite. Aplikasi ini mencakup:

  • Menambah tugas

  • Menampilkan daftar tugas

  • Mengedit tugas

  • Menghapus tugas

✅ Struktur Proyek:

lib/
├── main.dart
├── models/
│   └── todo.dart
├── screens/
│   └── home_screen.dart
├── db/
│   └── db_helper.dart

1. pubspec.yaml – Tambahkan dependency:

dependencies:
  flutter:
    sdk: flutter
  sqflite: ^2.3.0
  path: ^1.8.3
  path_provider: ^2.1.1

Lalu jalankan:

flutter pub get

2. lib/models/todo.dart

class Todo {
  final int? id;
  final String title;

  Todo({this.id, required this.title});

  Map<String, dynamic> toMap() {
    return {'id': id, 'title': title};
  }

  factory Todo.fromMap(Map<String, dynamic> map) {
    return Todo(
      id: map['id'],
      title: map['title'],
    );
  }
}

3. lib/db/db_helper.dart

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

class DBHelper {
  static Database? _db;

  static Future<Database> _initDb() async {
    final path = join(await getDatabasesPath(), 'todo.db');

    return openDatabase(
      path,
      version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE todos (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT NOT NULL
          )
        ''');
      },
    );
  }

  static Future<Database> get db async {
    _db ??= await _initDb();
    return _db!;
  }

  static Future<int> insertTodo(Todo todo) async {
    final dbClient = await db;
    return await dbClient.insert('todos', todo.toMap());
  }

  static Future<List<Todo>> getTodos() async {
    final dbClient = await db;
    final List<Map<String, dynamic>> maps = await dbClient.query('todos');
    return maps.map((map) => Todo.fromMap(map)).toList();
  }

  static Future<int> updateTodo(Todo todo) async {
    final dbClient = await db;
    return await dbClient.update(
      'todos',
      todo.toMap(),
      where: 'id = ?',
      whereArgs: [todo.id],
    );
  }

  static Future<int> deleteTodo(int id) async {
    final dbClient = await db;
    return await dbClient.delete('todos', where: 'id = ?', whereArgs: [id]);
  }
}

4. lib/screens/home_screen.dart

import 'package:flutter/material.dart';
import '../db/db_helper.dart';
import '../models/todo.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<Todo> todos = [];
  final TextEditingController _controller = TextEditingController();
  int? editingId;

  @override
  void initState() {
    super.initState();
    _refreshTodos();
  }

  void _refreshTodos() async {
    final data = await DBHelper.getTodos();
    setState(() {
      todos = data;
    });
  }

  void _addOrUpdateTodo() async {
    if (_controller.text.trim().isEmpty) return;

    if (editingId == null) {
      await DBHelper.insertTodo(Todo(title: _controller.text.trim()));
    } else {
      await DBHelper.updateTodo(
        Todo(id: editingId, title: _controller.text.trim()),
      );
    }

    _controller.clear();
    editingId = null;
    _refreshTodos();
  }

  void _deleteTodo(int id) async {
    await DBHelper.deleteTodo(id);
    _refreshTodos();
  }

  void _startEditing(Todo todo) {
    _controller.text = todo.title;
    editingId = todo.id;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('To-Do List')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(12),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      labelText: 'Enter todo',
                      border: OutlineInputBorder(),
                    ),
                  ),
                ),
                const SizedBox(width: 10),
                ElevatedButton(
                  onPressed: _addOrUpdateTodo,
                  child: Text(editingId == null ? 'Add' : 'Update'),
                ),
              ],
            ),
          ),
          Expanded(
            child: todos.isEmpty
                ? const Center(child: Text('No todos yet.'))
                : ListView.builder(
                    itemCount: todos.length,
                    itemBuilder: (context, index) {
                      final todo = todos[index];
                      return ListTile(
                        title: Text(todo.title),
                        trailing: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            IconButton(
                              icon: const Icon(Icons.edit),
                              onPressed: () => _startEditing(todo),
                            ),
                            IconButton(
                              icon: const Icon(Icons.delete),
                              onPressed: () => _deleteTodo(todo.id!),
                            ),
                          ],
                        ),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }
}

5. lib/main.dart

import 'package:flutter/material.dart';
import 'screens/home_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'To-Do List CRUD',
      theme: ThemeData(primarySwatch: Colors.teal),
      home: const HomeScreen(),
      debugShowCheckedModeBanner: false,
    );
  }
}

Jika kamu butuh versi dengan desain UI kekinian (pakai Flutter UI library), atau fitur tambahan seperti checklist, deadline, atau notifikasi, tinggal bilang aja ya!

Mau saya bantu buatkan juga versi APK-nya?

Post a Comment

0 Comments