Search code examples
flutterflutter-listviewstream-builderflutter-isar

Create ListView.builder from StreamBuilder with ISAR Database


I am trying to create a ListView.builder from StreamBuilder in Flutter.

TodoList class:

import 'package:isar/isar.dart';

part 'todo_list.g.dart';

@Collection()
class TodoList {
  Id id = Isar.autoIncrement;
  late String todoTitle;
}

IsarService class:

class IsarService {
  IsarService() {
    db = openDB();
  }

  late Future<Isar> db;

  // Return IsarDB, if not found, then create
  Future<Isar> openDB() async {
    if (Isar.instanceNames.isEmpty) {
      return await Isar.open(
        [TodoListSchema],
        inspector: true,
      );
    }
    return Future.value(Isar.getInstance());
  }

  Stream<List<TodoList>> listenToTodoList() async* {
    final isar = await db;
    yield* isar.todoLists.where().watch(fireImmediately: true);
  }
}

ListScreen widget:

class ListScreen extends StatefulWidget {
  const ListScreen(this.service, {super.key});

  final IsarService service;

  @override
  State<ListScreen> createState() => _ListScreenState();
}

class _ListScreenState extends State<ListScreen> {
  // Text Controller
  final _textController = TextEditingController();
  final service = IsarService();
  // Let's build List Title from snapshot
  final List<TodoList> _todoList = [];

  // Root widget of the class
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // List Screen Body Section
      body: StreamBuilder(
        stream: service.listenToTodoList(),
        builder: (context, snapshot) {
          if (snapshot.hasError) {
            AlertDialog(
              content: Text(snapshot.error.toString()),
            );
          } else if (snapshot.hasData) {
            _todoList.add(snapshot.data); // Error happen in this line
          }
          return const CircularProgressIndicator();
        },
      ),
    );
  }
}

Error:

The argument type 'List<TodoList>?' can't be assigned to the
parameter type 'TodoList'.

I'm trying to assign the snapshot data in final List<TodoList> _todoList = []; and use them in ListView.builder


Solution

  • Try this code:

    return Scaffold(
      body: StreamBuilder(
      stream: service.listenToTodoList(),
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          AlertDialog(
            content: Text(snapshot.error.toString()),
          );
        } else if (snapshot.hasData) {
          final todos = snapshot.data;
          if (todos != null) {
            return ListView.builder(
              itemCount: todos.length();
              itemBuilder: (context, index) {
                final todo = todos[index];
                return Text(todo.todoTitle);
              }
            );
          } else {
            return const Center(child: Text('No data found!'));
          }
        }
        return const CircularProgressIndicator();
        },
      ),
    );