When you have a large project, you probably want to manage data—you need to store it, fetch it from a server etc.
repository package introduces a bottom-up high-level data management abstraction layer that lets you do just that!
There are only a few key concepts:
Repositories can store objects.
Objects which are stored in repositories are called items.
Among all items in a repository, an item can be uniquely identified by its ID.
So, what can repositories do?
- Every repository can
fetchitems, returning a stream of items to the caller. Oftentimes, the stream will just contain one item, but there are times when it's very useful to return a sequence of items.
- Some repositories are finite, so you can
- Some repositories are mutable, so you can
There are already some repositories implemented. Here's just a quick look at three very different ones:
InMemoryStorageis a mutable and finite repository, allowing you to store objects in the device's memory.
JsonToStringTransformerstores items by serializing them and saving them to a provided
cacherepository. When fetching items, it first returns the item from the
cacheand returns the item from the
- Of course, you can also create your own repositories, i.e. one that downloads data from a server when items are fetched.
By now, you probably realized that all of these repositories only do very simple, deterministic tasks. Because that makes repositories modular, they can be composed into more powerful, higher-level repositories that elegantly handle the complex organization of streams from a variety of sources.
Here's an example of how that might look:
CachedRepository<Article>( source: ArticleDownloader(), cache: ObjectToJsonTransformer( serializer: ArticleSerializer(), source: JsonToStringTransformer( source: SharedPreferencesStorage(keyPrefix: 'articles'), ), ), )
If you're familiar with Flutter widgets, you'll immediately notice the style that favors composition over inheritance, allowing for incredibly flexible structures and abstractions.