cubix 0.1.5+4 copy "cubix: ^0.1.5+4" to clipboard
cubix: ^0.1.5+4 copied to clipboard

A predictable state management library that based on BLoc library. Easy to use and maintenance.

Cubix #

A predictable state management library that based on BLoc library. Easy to use and maintenance.

Lifecycle #

Cubix #

  • Constructor: Where to init the fields
  • onInit(): This method uses to perform some logics that needs everything ready (fields, dependencies)
  • onDispose(): This uses to dispose all disposable object
  • onDispatch(): This method will be called when the cubix dispatches an action

Action #

  • Constructor: Where to init the fields
  • onInit(): This method uses to perform some logics that needs everything ready (fields, dependencies)
  • onDispatch(): This method will be called when cubix dispatch the action
  • onDispose(): This uses to dispose all disposable object
  • onError(Object error): This method will be called when an error occurs while the action is dispatching
  • onSuccess(): This method will be called when the action is dispatched successfully
  • onDone(): This method will be called when the action is dispatched (no matter success or error)

Usages #

Simple Cubix #

// create a cubix
import 'package:cubix/cubix.dart';
import 'package:cubix/cubix_widgets.dart';
import 'package:flutter/material.dart';

class CounterCubix extends Cubix<int> {
  CounterCubix() : super(0);

  // method base action
  void increment() => state++;

  @override
  onDispatch(ActionBase action) {
    // tracking action dispatching
    // cannot track method base actions (increment)
    print(action.runtimeType.toString());
  }
}

// class base action
// using SyncAction for sync code
class DecrementAction extends SyncAction<void, int> {
  final int step;

  DecrementAction([this.step = 1]);

  @override
  body() {
    // update state
    state -= step;
  }
}

class DecrementAsyncAction extends AsyncAction<void, int> {
  final int step;

  DecrementAsyncAction([this.step = 1]);

  @override
  body() async {
    // delay in 2 seconds
    await Future.delayed(const Duration(seconds: 2));
    // perform increment by dispatch another action
    dispatch(DecrementAction(step));
  }
}

void main() => runApp(const App());

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

  @override
  build(context) {
    return CubixProvider(
        // build widget from CounterCubix
        // the builder receives BuildContext and Cubix objects
        child: CounterCubix.new.build((context, cubix) {
      return Column(children: [
        // getting state of cubix
        Text(cubix.state.toString()),
        ElevatedButton(
          // resolve cubix from context object
          onPressed: context.cubix(CounterCubix.new).increment,
          child: const Text('Increment'),
        ),
        ElevatedButton(
          // dispatch class base action
          onPressed: () => cubix.dispatch(DecrementAction()),
          child: const Text('Decrement'),
        ),
        ElevatedButton(
          // dispatch class base action with args
          onPressed: () => cubix.dispatch(DecrementAsyncAction(2)),
          child: const Text('Decrement Async'),
        )
      ]);
    }));
  }
}

Referencing other cubixes #

class UserCubix extends Cubix<User> implements IResolvable {}

class ArticleListCubix extends Cubix<List<Article>> {
    ArticleListCubix(): super([]);

    @override
    onResolve() async {
        final user$ = resolve(UserCubix.new);
        state = await LoadArticleByUser(user$.state.id);
    };
}

Auto Sync #

class ACubix extends Cubix<int> {
    ACubix(): super(0);
}

class BCubix extends Cubix<int> {
    ACubix(): super(0);
}

class SumCubix extends Cubix<int> implements IResolvable {
    SumCubix(): super(0);

    @override
    onResolve() {
        final a$ = resolve(ACubix.new);
        final b$ = resolve(BCubix.new);

        // can invoke dependency cubix method
        a$.doSomething();
        b$.doSomething();

        watch([a$, b$], (cancelToken) {
          state = a$.state + b$.state;
        });
    }
}

Listening action dispatching #

abstract class User {}

// define some user types
class AnonymousUser extends User {}

class AuthenticatedUser extends User {
    final Object data;
    const AuthenticatedUser(this.data);
}

// define cubix
class UserCubix extends Cubix<User> {
    // at begining time, cubix has an AnonymousUser state
    UserCubix(): super(AnonymousUser()) {
      // listen logout
      when((action) {
          // when action logout is dispatched
          if (action is LogoutAction) {
              // change current user to anonymous
              state = AnonymousUser();
          }
      });
      dispatch(LoadUserAction());
    }
}

class LoadUserAction extends AsyncAction<void, User> {
    @override
    body() async {
        final userData = await LoadUserData();
        state = AuthenticatedUser(userData);
    }
}

// VoidAction is an no body action
class LogoutAction extends VoidAction<User> {}

Cubix and Action compatible #

class CanStoreAnythingCubix extends Cubix<Object?> {
    CanStoreAnythingCubix(): super(null);
}

class IncrementAction extends SyncAction<void, int> {
    @override
    body() => state++;
}

final cubix = CanStoreAnythingCubix();
// there is no compiler error because ActionState (int) is compatible with CubixState (Object?)
// but you will get runtime exception: Cannot dispatch this action. The Action is not compatible with this Cubix
cubix.dispatch(IncrementAction());

Listen for dispatched action #

class CounterCubix extends Cubix<int> {
    CounterCubix(): super(0);
}
class IncrementAsyncAction extends AsyncAction<void, int> {
    @override
    body() async {
        await Future.delayed(const Duration(seconds: 1));
        state++;
    }
}
final cubix = CounterCubix();
cubix.dispatch(IncrementAsyncAction()..on(
    success: () => print('action dispatches successfully'),
    error: () => print('something went wrong'),
    done: () => print('action dispatched')
));

Watching cubix state changing #

There are two ways for watching cubix state changing: in cubix class and in cubix action

class RootCubix extends VoidCubix implements IResolvable {
  RootCubix(): super(0);

  @override
  onResolve() {
    final counter$ = resolve(CounterCubix.new);

    // watch counter cubix's state changing
    final removeWatcher = watch([counter$], (cancelToken) {
      print(counter$.state);
    });
  }
}

class CounterCubix extends Cubix<int> {
  CounterCubix(): super(0);
}

class CounterWatcherAction extends VoidAsyncAction<void> {
  @override
  body() async {
    final counter$ = resolve(CounterCubix.new);

    while(true) {
      // unlikely cubix.watch(), action.watch() returns future object
      await watch([counter$]);
      print(counter$.state);
      // continue watching
    }
  }
}

Understanding Action object #

typedef MyCubixState = int;
typedef MyActionResult = bool;

class MyCubix extends Cubix<MyCubixState> {
  MyCubix(): super(0);
}

class MyAction extends AsyncAction<MyActionResult, MyCubixState> {
  @override
  body() async {
    await Future.delayed(const Duration(seconds: 5));
    return true;
  }
}

// dispatching action
final action = MyAction(); // at this time, the action is not binded, no dispatcher created
final result = cubix.dispatch(action); // the action is binded, the dispatcher is created and working
print(result); // the result is Future<bool> because action is AsyncAction, so the result must be Future type of MyActionResult (bool)
// when action is binded, we can invoke some methods to control action dispatching and access some properties to receive dispatching status
print(action.done); // false
print(action.error); // null
print(action.success); // false
action.cancel(); // cancel action dispatching
print(action.cancelled); // true
// after cancel the action, the result object is running forever
await result;
0
likes
140
pub points
28%
popularity

Publisher

unverified uploader

A predictable state management library that based on BLoc library. Easy to use and maintenance.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (LICENSE)

Dependencies

collection, flutter, flutter_bloc

More

Packages that depend on cubix