state_property

Creator: coderz1093

Last updated:

0 purchases

TODO
Add to Cart

Description:

state property

A library that implements the State Property pattern for resolving the behavior of systems based on their current states. An existing example of this pattern includes the Material State Property used by the Flutter library.
In the example from Flutter, a TextButton can resolve its styling based on whether it's in one or more states like hovered, pressed or focused.
TextButton(
onPressed: () {},
child: const Text('TextButton'),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.pressed) || states.contains(MaterialState.hovered)) {
return Colors.blue;
}
return Colors.grey;
}),
)
);
copied to clipboard
Usage 1: Generic Loading States #
Suppose we have a system that can be in 3 states: pending, success and fail. These set of states can describe any system that can take on a task and have it work or fail, such as an API call made over a network or reading data from a file system. Each state will have corresponding behavior, which we can codify with state properties as shown below:
import 'package:state_property/state_property.dart';

enum LoadingStates {
loading,
success,
fail,
}

abstract class LoadingStateProperty<ResolverType>
implements StateProperty<LoadingStates, ResolverType> {
@override
ResolverType? resolve(Set<LoadingStates> states);

static StateProperty<LoadingStates, ResolverType> loading<ResolverType>(
StatelessResolver<ResolverType> resolver) =>
StateProperty.resolveState<LoadingStates, ResolverType>(
resolver,
LoadingStates.loading,
);

static StateProperty<LoadingStates, ResolverType> success<ResolverType>(
StatelessResolver<ResolverType> resolver) =>
StateProperty.resolveState<LoadingStates, ResolverType>(
resolver,
LoadingStates.success,
);

static StateProperty<LoadingStates, ResolverType> fail<ResolverType>(
StatelessResolver<ResolverType> resolver) =>
StateProperty.resolveState<LoadingStates, ResolverType>(
resolver,
LoadingStates.fail,
);

static StateProperty<LoadingStates, ResolverType> resolveWith<ResolverType>(
StatefulResolver<LoadingStates, ResolverType> resolver) =>
StateProperty.resolveWith<LoadingStates, ResolverType>(
resolver,
);

static StateProperty<LoadingStates, ResolverType> all<ResolverType>(
StatelessResolver<ResolverType> resolver) =>
StateProperty.all<LoadingStates, ResolverType>(
resolver,
);

static StateProperty<LoadingStates, Null> never<ResolverType>(
StatelessResolver<ResolverType> resolver) =>
StateProperty.never();
}
copied to clipboard
Our LoadingStatePropery class implements the StateProperty interface provided by the library to define a system that can be in any of our three loading states. It reuses the 4 core state properties from the library to build its loading state properties:

resolveWith - The most flexible state property that allows for dynamically resolving behavior based on the provided set of states.

final isLoadingStateProperty = LoadingStateProperty.resolveWith<bool>((states) {
return states.contains(LoadingStates.loading);
});

isLoadingStateProperty.resolve({LoadingStates.loading}); // true
isLoadingStateProperty.resolve({LoadingStates.success}); // false
copied to clipboard

resolveState - Resolves the given behavior when in the provided state, otherwise null.

final successStateProperty = LoadingStateProperty.resolveWith<bool>(() {
return true;
}, LoadingStates.done);

successStateProperty.resolve({LoadingStates.done}); // true
successStateProperty.resolve({LoadingStates.loading}); // false
copied to clipboard

all - Resolves the given behavior independent of the current state of the system.

final trueStateProperty = LoadingStateProperty.all<bool>(() {
return true;
});

trueStateProperty.resolve({LoadingStates.done}); // true
trueStateProperty.resolve({LoadingStates.loading}); // true
copied to clipboard

never Resolves null as the behavior independent of the current state of the system.

final nullStateProperty = LoadingStateProperty.all<bool>(() {
return true;
});

nullStateProperty.resolve({LoadingStates.done}); // null
nullStateProperty.resolve({LoadingStates.loading}); // null
copied to clipboard
Usage 2: Using Loading States in Widgets #
Now that we've built a state property that describes of loading states, we can apply it to a Flutter widget that supports different builders based on the current loading state.
import 'package:flutter/material.dart';
import './loading_state_property.dart';

class Loader extends StatefulWidget {
final Future<void> Function() load;
LoadingStateProperty<Widget> builder;

@override
}

class _LoaderState extends State<_LoaderState> {
LoadingState _state;

@override
initState() {
super.initState();

// Kick off loading data when the widget is first built.
_state = LoadingStates.loading;
widget.load().then((_resp) {
setState(() {
_state = LoadingStates.success;
})
}).catchError((e) {
setState(() {
_state = LoadingStates.fail;
});
});
}

@override
build(context) {
return widget.builder.resolve(_state) ?? SizedBox();
}
}

// A widget that has different loading behavior based on the loading state.
class MyLoadingWidget extends StatelessWidget {
@override
build(context) {
return Loader(
builder: LoadingStateProperty.resolveWith<Widget>((states) {
if (states.contains(LoadingStates.success)) {
return Text('Done!');
}

if (states.contains(LoadingStates.fail)) {
return Text('Something went wrong');
}

return const CircularProgressIndicator();
});
)
}
}

// A widget that only has UI when the loading has finished successfully.
class SuccessfulLoadingWidget extends StatelessWidget {
@override
build(context) {
return Loader(
builder: LoadingStateProperty.resolveState<Widget>(() => Text('Done!'), LoadingStates.success);
)
}
}
copied to clipboard

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files In This Product:

Customer Reviews

There are no reviews.