Halo teman-teman pada artikel sebelumnya kita sudah membuat StateManagement menggunakan BLoC yang nanti digunakan untuk mengelola dan memisahkan antara Logika Bisnis dengan UI. Langkah selanjutnya kita akan membuat tampilan yang nanti digunakan untuk menampilkan data todo list dari database Supabase.
Membuat UI Todo List
Sekarang teman-teman membuat folder dengan nama screen
di dalam folder /lib/
, lalu di dalam folder /lib/screen
buat file dengan nama todo_screen.dart
lalu kita ketik kode berikut:
import 'package:flutter/material.dart';
class TodoScreen extends StatefulWidget {
const TodoScreen({super.key});
@override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
@override
void initState() {
// TODO: Load Data Todo List
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Todo List')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
decoration: const InputDecoration(
hintText: 'Tambahkan tugas baru',
border: OutlineInputBorder(),
),
onSubmitted: (value) {},
),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: () {
// TODO: Tambah Data Todo List
},
child: const Text('Tambah'),
),
],
),
),
Expanded(
child: RefreshIndicator(
onRefresh: () async {
// TODO: Refresh Data Todo List
},
child: ListView.builder(
itemCount: 0, // TODO: Ganti dengan jumlah todo
itemBuilder: (context, index) {
return ListTile(
title: Text(
'Todo Item $index',
), // TODO: Ganti dengan data todo
trailing: Checkbox(
value: false, // TODO: Ganti dengan status isDone
onChanged: (value) {
// TODO: Update Data Todo List
},
),
);
},
),
),
),
],
),
);
}
}
setelah itu kita rubah file pada main.dart
menjadi berikut:
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:todo_list_supabase/screen/todo_screen.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: ".env");
final String supabaseUrl = dotenv.env['SUPABASE_URL'] ?? '';
final String supabaseAnonKey = dotenv.env['ANON_KEY'] ?? '';
await Supabase.initialize(url: supabaseUrl, anonKey: supabaseAnonKey);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const TodoScreen(),
);
}
}
Sekarang kita coba jalankan maka tampilannya kurang lebih seperti berikut:

Menampilkan Data dari Supabase
Setelah membuat Ui sekarang kita menampilkan data dari database, pertama kita impelementasikan BLoC Provider. Kita buka file main.dart
lalu ketik kode berikut:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:todo_list_supabase/cubit/todo_cubit.dart';
import 'package:todo_list_supabase/screen/todo_screen.dart';
import 'package:todo_list_supabase/service/todo_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: ".env");
final String supabaseUrl = dotenv.env['SUPABASE_URL'] ?? '';
final String supabaseAnonKey = dotenv.env['ANON_KEY'] ?? '';
await Supabase.initialize(url: supabaseUrl, anonKey: supabaseAnonKey);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final TodoService service = TodoService();
MyApp({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => TodoCubit([], service),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const TodoScreen(),
),
);
}
}
Perubahan kode di atas terletak pada kelas MyApp()
, kita initialisasi TodoService
yang nanti kita masukkan pada TodoCubit
.
class MyApp extends StatelessWidget {
final TodoService service = TodoService();
MyApp({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => TodoCubit([], service),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const TodoScreen(),
),
);
}
}
Selanjutnya kita buka file todo_screen.dart
lalu ketik kode berikut:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:todo_list_supabase/cubit/todo_cubit.dart';
import 'package:todo_list_supabase/model/todo_model.dart';
class TodoScreen extends StatefulWidget {
const TodoScreen({super.key});
@override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
@override
void initState() {
context.read<TodoCubit>().fetchTodos(); // Fetch todos on init
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Todo List')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
decoration: const InputDecoration(
hintText: 'Tambahkan tugas baru',
border: OutlineInputBorder(),
),
onSubmitted: (value) {},
),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: () {
// TODO: Tambah Data Todo List
},
child: const Text('Tambah'),
),
],
),
),
Expanded(
child: RefreshIndicator(
onRefresh: () async {
// TODO: Refresh Data Todo List
},
child: BlocBuilder<TodoCubit, List<TodoModel>>(
builder: (context, state) {
final todos = state;
if (todos.isEmpty) {
return const Center(
child: Text(
'Belum ada tugas',
style: TextStyle(fontSize: 18),
),
);
}
return ListView.builder(
itemCount: todos.length, // TODO: Ganti dengan jumlah todo
itemBuilder: (context, index) {
final todo = todos[index];
return ListTile(
title: Text(
todo.title,
style: TextStyle(
decoration: todo.isDone
? TextDecoration.lineThrough
: null,
),
), // TODO: Ganti dengan data todo
leading: Checkbox(
value: todo.isDone,
onChanged: (_) {
// TODO: Update status todo
},
),
trailing: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () {
// TODO: Hapus data todo
},
),
);
},
);
},
),
),
),
],
),
);
}
}
Perubahan kode di atas yang pertama kita memanggil method fetchTodos()
dari TodosCubit
yang sudah kita buat di dalam method initState()
.
@override
void initState() {
context.read<TodoCubit>().fetchTodos(); // Fetch todos on init
super.initState();
}
Lalu kita bungkus ListView.builder()
dengan BlockBuilder()
untuk menampilkan data.
BlocBuilder<TodoCubit, List<TodoModel>>(
builder: (context, state) {
final todos = state;
if (todos.isEmpty) {
return const Center(
child: Text(
'Belum ada tugas',
style: TextStyle(fontSize: 18),
),
);
}
return ListView.builder(
itemCount: todos.length, // TODO: Ganti dengan jumlah todo
itemBuilder: (context, index) {
final todo = todos[index];
return ListTile(
title: Text(
todo.title,
style: TextStyle(
decoration: todo.isDone
? TextDecoration.lineThrough
: null,
),
), // TODO: Ganti dengan data todo
leading: Checkbox(
value: todo.isDone,
onChanged: (_) {
// TODO: Update status todo
},
),
trailing: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () {
// TODO: Hapus data todo
},
),
);
},
);
},
),
Kita juga melakukan pengecekan jika data tidak ada maka akan menampilkan sebuah widget Text
dengan tulisan Belum ada tugas, jika ada maka akan menampilkan data berupa widget ListTile()
.
Sekarang kita jalankan maka tampilannya kurang lebih seperti berikut:

Untuk menampilkan data tugas coba kita isi data di dalam Supabase dengan cara kita buka menu Table Editor -> Pilih tabel -> Create Table


Setelah kita memasukkan data maka tampilan android kurang lebih seperti berikut:

Kesimpulan
Pada tutorial kali ini kita sudah membuat ui untuk menampilkan data dari database supabase, dan mencoba memasukkan data secara manual menggunakan supabase langsung, pada tutorial selanjutnya kita akan membuat fungsi untuk mencentang todo list kita.
Ebook Premium
Membangun Dashboard dan Aplikasi Android Food Store Dengan Laravel Filament, Flutter dan Payment Gateway
Membangun Aplikasi Donasi Online dengan Laravel, Flutter dan Payment Gateway