renderer 0.0.5 renderer: ^0.0.5 copied to clipboard
A Falcon micro-framework package to manage UI states reactively based on custom BLoC and reactive extenstions
Introduction #
What is Renderer?
A Falcon micro-framework package to manage UI states reactively based on custom BLoC and reactive extenstions.
Why Renderer?
Renderer came to be able to inject the refeshing UI states reactively in flutter widget tree with minimum effort.
Installation #
dependencies:
renderer: [latest-version]
Setup and Usage #
Preparing BLoC
- Create your BLoC event abstract class and let it inherit from
RendererEvent
abstract class AuthEvent extends RendererEvent {}
- Create your BLoC state abstract class and let it inherit from
RendererState
abstract class AuthState extends RendererState {}
- Create a BLoC class to include your logic and let it inherit from
RendererBLoC
abstract class.RendererBLoC<V, S>
is a generic class so it expects to start with both Event and State types respectively. Finally, implement bothdispatch()
anddispose()
functions, noting thatdispose()
only needs to call the already inheritedcloseSubject()
function.
class AuthBloc extends RendererBLoC<AuthEvent, AuthState> {
@override
void dispatch(AuthEvent event) async {}
@override
void dispose() {
closeSubject();
}
}
4- Finally, to notify Renderers about a new state, all you need to do is calling the already inherited function notifyRenderers()
and pass your great state object to it as an argument.
class AuthBloc extends RendererBLoC<AuthEvent, AuthState> {
@override
void dispatch(AuthEvent event) async {
if (event is LoginEvent) {
notifyRenderers(LoginSuccess('User Logged In'));
}
}
@override
void dispose() {
closeSubject();
}
}
Preparing Widgets
Renderer carries the burden of using always a Stateful Widget to repaint your UI states away of your shoulders. It helps get rid of the extensive boilerplate code used to be added inside initState()
as will as cancelling any state stream subscriptions inside dispose()
.
- Inside your Stateless Widget let your class implements
RendererFire
mixin.
class HomeScreen extends StatelessWidget with RendererFire {}
- In your
build()
widget tree, wrap the widget that expects data from a state inside aRenderer
widget. ARenderer<B, S>
is a generic widget that expects both a BLoC and success State types respectively. The Renderer will NOT allow its child widget to refresh until it receives one of the 3 pre-defined (Success, Error or Loading) states.
class HomeScreen extends StatelessWidget with RendererFire {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: () {
fireEvent<AuthBloc, LoginEvent>(LoginEvent(status: 'User Logged In'));
}),
body: Center(
child: Renderer<AuthBloc, LoginSuccess>(
errorWhen: (errorState) => errorState is LoginError,
loadingWhen: (state) => state is LoginLoading,
stateBuilder: (state) => Center(
child: Text(
state.message,
style: const TextStyle(color: Colors.green, fontSize: 40),
),
),
onLoading: const CircularProgressIndicator(),
errorBuilder: (String message, int code) => Center(
child: Text('$message, CODE: $code',
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.red, fontSize: 60)),
),
),
),
);
}
}
-
For each renderer widget, you're required to guide the renderer when to replace the success state UI with an error or loading UI using
errorWhen
,loadingWhen
callbacks. -
For a loading state, you're required to provide the
onLoading
widget to render when the renderer receives the loading state using the defined earlierloadingWhen
. -
For an error state, you're required to provide either the
onError
widget to statically render an error widget orerrorBuilder
to get the exact error message and error code when the renderer receives the error state using the defined earliererrorWhen
. -
Finally, Firing the event is no longer needs an instance of a BLoC as usual. You just need to call
fireEvent()
function that is already inherited fromRendererFire
mixin.fireEvent<B, V>
is a generic function that expects both BLoC and Event types respectively.
fireEvent<AuthBloc, LoginEvent>(LoginEvent(status: 'User Logged In'));