flutter_data_stream_builder 0.0.3 flutter_data_stream_builder: ^0.0.3 copied to clipboard
A pragmatic StreamBuilder with sensible defaults
DataStreamBuilder #
A pragmatic StreamBuilder
with sensible defaults.
😩 The problem with StreamBuilder #
StreamBuilder
is an essential tool to work with BLoCs or generally any stream.
But with enough streams in our codebase, a lot of boilerplate is introduced. Code gets repetitive and can't be easily reused:
StreamBuilder(
stream: bloc.stock,
builder: (context, AsyncSnapshot<Stock> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.stock.toString());
} else if (snapshot.hasError) {
return Text(snapshot.error.toString());
}
return Center(child: CircularProgressIndicator());
},
),
DataStreamBuilder
aims to fix these issues for the common usecase:
StreamBuilder(
stream: bloc.stock,
builder: (context, Stock stock) => Text(stock.local.toString())
),
This library provides default builders for the loading and error states (can be supplied as loadingBuilder
and errorBuilder
), and only calls builder
when data is present.
Note: if you need fine-grained control over ConnectionState
s to the underlying computation, just use StreamBuilder
.
👩🏾💻 Usage #
Using defaults for loading and error states:
DataStreamBuilder<List<Post>>(
stream: Repository.of<Post>().findAll(),
builder: (context, List<Post> posts) => ListView(
children: posts.map((post) => ListTile(title: Text(post.body))).toList(),
)
)
Custom loading and error widgets:
DataStreamBuilder<List<Post>>(
stream: Repository.of<Post>().findAll(),
loadingBuilder: (context) => Center(child: Text('Loading posts...')),
errorBuilder: (context, error) => PostErrorView(error),
builder: (context, List<Post> posts) => ListView(
children: posts.map((post) => ListTile(title: Text(post.body))).toList(),
)
)
See tests and the Example tab for a full example.
🛠 Extending #
We can easily extend the class in order to provide our own app-wide defaults.
For instance, we could implement a branded loader:
class BrandedDataStreamBuilder<T> extends DataStreamBuilder<T> {
static final brandedLoadingBuilder = (context) => Text('Custom branded loading...');
BrandedDataStreamBuilder({
Key key,
@required Stream<T> stream,
@required DataWidgetBuilder<T> builder,
DataErrorWidgetBuilder errorBuilder
}) :
assert(builder != null),
super(
key: key,
stream: stream,
builder: builder,
loadingBuilder: brandedLoadingBuilder,
errorBuilder: errorBuilder
);
}
In action:
➕ Collaborating #
Please use Github to open issues and send PRs. Thanks 🙌
📝 License #
MIT