lite_state

Last updated:

0 purchases

lite_state Image
lite_state Images
Add to Cart

Description:

lite state

Flutter Lite State #



The litest state machine ever. You don't need to depend on any heavy libraries
if you only need to control state of your widgets.
This state manager is for those who are tired of writing
lots of boilerplate code of states like in case of using BLoC,
or don't want to depend on BuildContext like with using Provider
or just don't want tons of functionality in one place like with using Get.
I personally do like those state managers but I also see their disadvantages in some usecases. They just don't fit some projects. That's why I decided to write LiteState for the projects that need to be up and running in just a couple of minutes
Lite State is very simple and lite. It consists of a single file.
The purpose of LiteState is to make writing and using controllers as
quick and easy as possible. I wish I could do them even simplier
by using reflection, so that one don't even need to instantiate controllers
but unfortunately, Flutter doesn't support mirrors :(
Anyway, just take a look at the example below
You might also like my other packages
flutter_multi_formatter



flutter_instagram_storyboard

Features #
Easily controlling the state of your widgets without a need for context. That's it.
Getting started #
All your Lite State controllers must be inherited from LiteStateController
generic class. All the magic is happening inside.

Create a controller you need. E.g. an auth controller to check users'
authorization

import 'package:lite_state/lite_state.dart';

class AuthController extends LiteStateController<AuthController> {

}
copied to clipboard



INITIALIZATION OF CONTROLLERS #
You have two options here #

Add initialization of your controller somewhere in the beginning of your app
e.g. in initState() {} of your main class

void main() {
runApp(const MyApp());
}

class MyApp extends StatefulWidget {
const MyApp({super.key});

@override
State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

@override
void initState() {
/// In this case I've used lazy initialization
/// this means the controller will be instantiated when it's first
/// used. Pay attention, I've used AuthController type as a key
/// in the instantiator Map. This is used internally to look for
/// a controller using generic constraints
/// In case you want to initialize all your controllers at once
/// just use initControllers() instead of initControllersLazy()
initControllersLazy({
AuthController:() => AuthController(),
LoaderController:() => LoaderController(),
});
super.initState();
}


@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: TestPage(),
);
}
}
copied to clipboard
Just you LiteState builder any where you need
Widget build(BuildContext context) {
return LiteState<AuthController>(
builder: (BuildContext c, AuthController controller) {
/// ... your code goes here
},
);
}

copied to clipboard
OR #
You can use a single use controller like this
BE AWARE that in this case you controller will be disposed as soon
as LiteState widget, where you pass it, is disposed
The controller like this will override any other controller of the same time
that you might have initialized via initControllers or initControllersLazy
return LiteState<SingleUseController>(
controller: SingleUseController(),
builder: (BuildContext c, SingleUseController controller) {
return Scaffold(
appBar: AppBar(
title: const Text('Single Use Controller'),
),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
controller.counter.toString(),
style: const TextStyle(
fontSize: 50.0,
),
),
Button(
text: 'Update Counter',
onPressed: () {
controller.counter++;
},
),

],
),
),
);
},
);

copied to clipboard
Usage #


class TestPage extends StatelessWidget {
const TestPage({Key? key}) : super(key: key);

Widget _buildUserName() {
/// I use authController global property here instead of
/// calling findController<AuthController>()
/// but it does call findController inside. It's just a shorhand
return Text('Welcome, ${authController.userName}');
}

@override
Widget build(BuildContext context) {
return LiteState<AuthController>(
builder: (BuildContext c, AuthController controller) {
return Scaffold(
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildUserName(),
const SizedBox(height: 20.0),
Button(
isLoading: controller.isLoading,
text: controller.isAuthorized ? 'Log Out' : 'Authorize',
onPressed: () {
/// you can also use a shorthand method fc<AuthController>()
/// to do the same. It calls findController internally
/// or just write a global function to get it.
/// e.g. right above AuthController declaration
/// AuthController get authController {
/// return findController<AuthController>();
/// }
if (controller.isAuthorized) {
findController<AuthController>().logout();
} else {
findController<AuthController>().authorize();
}
},
),
const Padding(
padding: EdgeInsets.only(
left: 40.0,
right: 40.0,
top: 20.0,
),
child: Text(
'Notice that your authorization is stored across sessions in a persistant local storage. Reload the app and you will see that authorization is still there',
),
),
],
),
),
);
},
);
}
}
copied to clipboard
Controllers also allow you to easily store and restore
data from shared preferences. When the local data is restored
a controller calls void onLocalStorageInitialied(); method.
You can override it in your controllers to know the exact time
when your local data is ready.
This example shows how you can store and restore auth tokens
/// First you need to create a class that you want to
/// be storable / restorable. The class must implement
/// LSJsonEncodable interface. It's very simple and is needed
/// for a LiteState controller to determin if and instance of the
/// class can be serialized according to its rules.
/// The interface only contains one method: Map encode();
/// which must be overriden in your class
class AuthData implements LSJsonEncodable {
String type;
String token;
String userName;
AuthData({
required this.type,
required this.token,
required this.userName,
});

@override
Map encode() {
return {
'type': type,
'token': token,
'userName': userName,
};
}
/// The static method is necessary as a decoder
/// so that a controller can understand how to work with your data
/// when it meet the data in SharedPreferences
/// You can see how it's used below
static AuthData decode(Map map) {
return AuthData(
type: map['type'],
token: map['token'],
userName: map['userName'],
);
}
}

copied to clipboard
Now you need to initialize your decoders. The best place to do it is
right before you initialize your controllers. Somewhere in the beginning of your app
@override
void initState() {

/// Initialize decoders. In this case we only have AuthData decoder
/// but you will need to add decoders for every class you want to be encodable / decodable
initJsonDecoders({
AuthData: AuthData.decode,
});

initControllersLazy({
AuthController:() => AuthController(),
LoaderController:() => LoaderController(),
});
super.initState();
}
copied to clipboard
That's basically it. Now you can simply use it in your controller.
AuthController get authController {
return findController<AuthController>();
}

class AuthController extends LiteStateController<AuthController> {

AuthData? get authData {
return getPersistentValue<AuthData>('authData');
}
set authData(AuthData? value) {
setPersistentValue<AuthData>('authData', null);
}

String get userName {
return authData?.userName ?? 'Guest';
}
...
}

copied to clipboard
See example project for a complete source

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.