spread_core 0.0.6 copy "spread_core: ^0.0.6" to clipboard
spread_core: ^0.0.6 copied to clipboard

Easiest to implement state management for Dart. Use any primitive, enum, type or entity as state. Support state event multicasting

example/lib/main.dart

import 'dart:math';

import 'package:spread_core/spread_core.dart';

void main() async {
  await initServices();
  await initObservers();
  LoadUsersUseCase().execute();
}

Future initServices() async {
  Services()
      .init(userService: () => UserServiceImpl(repository: PostsApiPort()));
}

Future initObservers() async {
  UsersObserver().selfRegister();
}

// our ports:

abstract class PostsPort {
  Future<List<User>> findAllUsers();
}

class PostsApiPort implements PostsPort {
  Random random = Random();

  @override
  Future<List<User>> findAllUsers() async {
    final id = random.nextInt(1000);
    return Future.delayed(
        const Duration(
          seconds: 2,
        ),
        () => [
              User(id: id, name: "aaaa").generatePosts(),
              User(id: id + 500, name: "bbbb").generatePosts()
            ]);
  }
}

// our services:

abstract class UserService {
  Future<List<User>> getUsers();
}

class UserServiceImpl implements UserService {
  final PostsPort repository;

  UserServiceImpl({required this.repository});

  @override
  Future<List<User>> getUsers() async {
    return repository.findAllUsers();
  }
}

class Services {
  static final Services _singleton = Services._internal();
  factory Services() {
    return _singleton;
  }
  Services._internal();
  late final UserService userService;

  void init({
    required UserService Function() userService,
  }) async {
    this.userService = userService.call();
  }
}

// our models:

class User with StateEmitter implements Entity {
  final int id;
  final String name;
  final List<UserPost> posts = List.empty(growable: true);

  User({required this.id, required this.name});

  dynamic toDynamic() => {'id': id, 'name': name};

  static User fromDynamic(dynamic user) =>
      User(id: user['id'], name: user['name']);

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is User && other.id == id && other.name == name;
  }

  @override
  int get hashCode => id.hashCode ^ name.hashCode;

  @override
  String toString() {
    return 'User{id: $id, name: $name}';
  }

  @override
  String get entityId => id.toString();

  User generatePosts() {
    _generateRandomPosts();
    return this;
  }

  void _generateRandomPosts() async {
    for (int i = 0; i < 100; i++) {
      final post = await _generateRandomPost();
      print('added post');
      posts.add(post);
      emitEntity<User>(this);
    }
  }

  Future<UserPost> _generateRandomPost() async {
    return Future.delayed(
        const Duration(
          seconds: 1,
        ),
        () => UserPost(content: 'random content'));
  }
}

class UserPost {
  final String content;

  UserPost({required this.content});
}

// our states:

abstract class UsersState {}

class LoadingUsers extends UsersState {}

class LoadedUsersSuccess extends UsersState {
  final List<User> users;

  LoadedUsersSuccess({required this.users});
}

class LoadedUsersFail extends UsersState {
  final Object? error;
  final StackTrace? stackTrace;

  LoadedUsersFail({required this.error, required this.stackTrace});
}

// our use case:

class LoadUsersUseCase with StateEmitter implements UseCase {
  @override
  void execute() async {
    final List<User>? usersCached =
        SpreadState().getNamed<List<User>>("users_cache");
    if (usersCached != null) {
      emit<UsersState>(LoadedUsersSuccess(users: usersCached));
    } else {
      emit<UsersState>(LoadingUsers());
      Services().userService.getUsers().then((users) {
        emitNamed("users_cache", users);
        emit<UsersState>(LoadedUsersSuccess(users: users));
      }).onError((error, stackTrace) {
        emit<UsersState>(LoadedUsersFail(error: error, stackTrace: stackTrace));
      });
    }
  }
}

// Create a State observer service to listen and handle states asynchronously

class UsersObserver extends SpreadObserver<UsersState> {
  @override
  onState(UsersState state) {
    print("UsersObserver Observed: ${state.toString()}");
  }
}
6
likes
160
points
18
downloads

Publisher

verified publisherautanalabs.com

Weekly Downloads

Easiest to implement state management for Dart. Use any primitive, enum, type or entity as state. Support state event multicasting

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

More

Packages that depend on spread_core