Create local data source and add hive
Data Layer
Summary
This lesson focuses on setting up the local data source for the Home feature in a Clean Architecture Flutter app. The instructor creates the abstract contract and implementation for HomeLocalDataSource, notably changing the return types from asynchronous Futures to synchronous lists, assuming instant access from a local cache. The lesson then transitions to choosing a local caching solution, selecting the Hive NoSQL package over SQLite due to its speed and simplicity for non-relational API responses, and concludes by installing the necessary Hive and code-generation dependencies.
Key Ideas
- HomeLocalDataSource abstract class defines the contract for fetching cached BookEntity data.
- Return types for local data fetching are set to synchronous List<BookEntity> rather than Future<List<BookEntity>> to reflect instant cache access.
- Small, atomic Git commits are recommended to make discarding erroneous changes safer and easier.
- Hive is selected over SQL (SQLite) because the data is fetched directly from an API and lacks complex relational requirements.
- hive and hive_flutter are added as standard dependencies for database operations.
- hive_generator and build_runner are strictly added as dev_dependencies to handle TypeAdapter code generation without bloating the production app.
Code Snippets
import '../../domain/entities/book_entity.dart';
abstract class HomeLocalDataSource {
List<BookEntity> fetchFeaturedBooks();
List<BookEntity> fetchNewestBooks();
}
class HomeLocalDataSourceImpl extends HomeLocalDataSource {
@override
List<BookEntity> fetchFeaturedBooks() {
// TODO: implement fetchFeaturedBooks
throw UnimplementedError();
}
@override
List<BookEntity> fetchNewestBooks() {
// TODO: implement fetchNewestBooks
throw UnimplementedError();
}
}dependencies:
# ... other dependencies
hive: ^2.2.3
hive_flutter: ^1.1.0
dev_dependencies:
# ... other dev dependencies
hive_generator: ^2.0.0
build_runner: ^2.3.3Architecture Insight
Hive is a fast key-value store, but it's an implementation detail. The local data source's contract is "give me the cached featured books" — Hive, SQLite, or a JSON file behind the scenes shouldn't matter to anyone above.
Generated TypeAdapters are a Hive-specific concept. Keeping them next to the model (in data/) preserves the rule: the domain layer never imports hive or any persistence package.
My Notes
The instructor makes a deliberate choice to drop Future from the local data source method signatures. This is a crucial architectural decision: it dictates that the chosen local storage must support synchronous reads. Hive supports this beautifully via box.get(), which reads directly from an in-memory map once the box is opened. [Editor's note] Be careful with this approach if you ever plan to swap Hive for SQLite/sqflite or Isar in the future, as those libraries strictly rely on asynchronous I/O (Future). By making the data source contract synchronous, you tightly couple your LocalDataSource abstraction to Hive's specific in-memory architecture. Additionally, the instructor's point on small, frequent Git commits is an excellent real-world software engineering practice. Keeping commits tightly scoped to single features or dependency additions prevents massive headaches when using git restore or discarding changes later.