Yaz State and Content Manager For Flutter Client

Related tags

Templates yaz
Overview

pub package style: effective dart License: MIT GitHub code size in bytes

yaz

Yaz Package for State, Content and User's Options Managements

Example

Introduction

This package is supported for Web, Mobile and Desktop applications.

Yaz Package is consisted of two parts;

1) State Management

Demo App Video

  • Yaz Package is a state management package in the first place. It uses only ChangeNotifier for the whole process, due to this it is really simple and fast. It uses only one widget. Widget of "YazListenerWidget"

  • Yaz helps you to convert any objects to ChangeNotifier with a simple code.

  • Yaz supports for collection changes both in separate or entirely.

2) Content Management

  • Yaz provides you to get and change user options by a simple code from any part of the application.

  • Yaz helps you to store and cache your app's Frequently Used Contents.

Example of Flutter Counter App

/// You don't need a stateful widget
class MyHomePage extends StatelessWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  /// 1 ) Define your variable and convert notifier
  final counter = 0.notifier;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            /// 2 ) Convert Widget your ChangeNotifier
            counter.builder((context) => Text(
                  '${counter.value}',
                  style: Theme.of(context).textTheme.headline4,
                )),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          /// 3) Increment Count
          counter.value++;
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Usage

How to Convert an Object to a Change Notifier?

Any object might be converted into a ChangeNotifier: YazNotifier

.notifier works on any object and returns a YazNotifier

    var counter = 0.notifier;
    var editing = "Mehmet Yaz".notifier; 
    var foo = Foo().notifier; 

.value gets and set an value in YazNotifier instance;

This setter triggers all listeners

    print(counter.value);
    // output - 0 -
    
    counter.value++;
    
    print(counter.value);
    // output - 1 -

! Attention:

If you wish to listen changes in instance members of foo :

    // DON'T
    var foo = Foo().notifier;
    // DO
    var bar = Foo().bar.notifier;

Because foo is triggered only like this;

    foo.value =  Foo(); // new instance
    foo.value = anotherFoo;

BuiltNotifier

You can see the widgets wrapped by BuiltNotifier when they are rebuilt. They blink when they are rebuilt.

  BuiltNotifier(
        child: YourWidget()
        );

Example

If you want to wrap all YazListenerWidget with BuiltNotifier on debug mode:

add to main function this expression

  UserOption<bool>.create(name:"always_notify_built_debug" , value: true);

YazListenerWidget

YazListenerWidget works with any ChangeNotifier instance. There is no other widget for state management.

    YazListenerWidget(
      changeNotifier: changeNotifier,
      builder: (BuildContext c) {
        return MyWidget();  
      }     
    );

Also you can create YazListenerWidget instance by .builder method works on any ChangeNotifiers.

  changeNotifier.builder((context) => MyWidget());

! Performance Tip:

Narrow down this widget as narrow as possible. Using more YazListenerWidgets is better than using a single widget to wrap all things.

Single Variable

  /// define notifier
  var counter = 0.notifier;

  /// Listen with widget
  YazListenerWidget(
    changeNotifier: counter,
    builder: (BuildContext c) {
    return Text(counter.value.toString());
  }
  
  //or

  counter.builder((context) => Text(counter.value.toString()))
);

Example

Multiple Variable

  /// define notifiers
  final counter1 = 0.notifier;
  final counter2 = 5.notifier;
  final counter3 = 10.notifier;

  /// Listen with widget
  YazListenerWidget(
    changeNotifier: counter1.combineWith([counter2, counter3]),
    /// or changeNotifier:  MultipleChangeNotifier([counter1 , counter2 ,counter3]),
    /// or changeNotifier: [counter1 , counter2, counter3].notifyAll
    builder: (BuildContext c) {
    return Text(counter.value.toString());
  }
);

Example

How to listen collection changes?

There are 3 ways to listen collections

1) Classical Total Changes - Bad Way

In this way, standard .notifier is used

But this triggers only like this;

    var list = [0,1,2,3].notifier
    
    list.value = [10 , 20 , 30]; // Triggered
    
    list.value[0] = 50; // Not Triggered

    // USAGE
    YazListenerWidget(
        changeNotifier: list,
        //....
    );

2) Triggering in any changes - Mid-Way

In this way, a YazList is created.

A YazList can be created by .listenAll from all List instances.

YazMap can be created from all Maps by this way, as well.

YazList is a ChangeNotifier and all listeners are triggered in any changes.

    YazList<int> list = [0,1,2,3].listenAll;
    list[0] = 5; // Triggered
    list.add(10) = 10; // Triggered
    list.remove(0) = 30; // Triggered
    /// triggered by all methods similarly
    // USAGE
    YazListenerWidget(
      changeNotifier: list,
      //....
    );

Example

3) Trigger every element separately - Good Way

You can get a List<YazNotifier> on any List by .listeners method.

In this way, value changes of elements trigger all listeners

When making length-changings like adding or removing elements or making YazNotifier instance changes; listeners are NOT triggered.

For instance, let us assume that there are two separate widgets to listen index of 0 and index of 1. When index of 0 is changed, only the widget of 0 is rebuilt. Other one is not rebuilt.

To trigger all changes, .notifyAll method on List<YazNotifier> may be used.

var listeners = [0,1].listeners;

// 0. Widget
YazListenerWidget(
changeNotifier: listeners[0],
//....
);

// 1. Widget
YazListenerWidget(
changeNotifier: listeners[1],
//....
);

// 2. Widget
YazListenerWidget(
changeNotifier: listeners.notifyAll,
//....
);

listeners[0].value++; // Rebuilt 0. and 2. Widgets
listeners[1].value++; // Rebuilt 1. and 2. Widgets

Example

All can be applied on Map. You can get a Map<K, YazNotifier<V>> by .listeners on Map.

How to listen Stream?

All streams convertible by .yazStream or .yazStreamWithDefault(value) on Stream

.yazStream returns nullable YazStream<T?>

.yazStreamWithDefault(value) returns non-nullable YazStream<T>

YazStream<User?> stream = db.getChanges().yazStream;
stream.builder((context) => YourWidget());

/// DON'T FORGET
stream.cancel();

User Options

Simple Example

You can manage every user option by this service.

///
class MyHomePage extends StatelessWidget {
  ///
  MyHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        /// Wrap widgets with UserOption
        /// use default value or initialize on your splash screen
        child: OptionWrapper<double>(
          userOption: UserOption("font_size_multiplier", defaultValue: 0.5),
          builder: (c, option) {
            return Text(
              "User Option Example",
              style: TextStyle(fontSize: 10.0 * option.value), 
              /// Rebuild with new option
              /// or use directly :
              /// fontSize: 10.0 * UserOption("font_size_multiplier").value, 
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          /// Change options
          UserOption<double>("font_size_multiplier").value += 0.1;
        },
        tooltip: 'Increment Font Size',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Usage

You can get option in everywhere:

  UserOption<double>("font_size").value;

and you change

    UserOption<double>("font_size").value = 10.0;

You can wrap your widgets with options, when options are changed the widgets are rebuilt;

  OptionsWrapper(
    option: UserOption<double>("font_size"),
    builder : (c , option) {
      return Text("Hello World!" , style:TextStyle(
        fontSize: option.value
      ));  
    }   
  )

You can init by your default values;

  UserOptions().init(List<UserOption> list);

You can listen changes for to fetch on db

UserOptions().onUserOptionsChange((options){
  //fetch
});

If you don't use init functions, you may set default values in the first use. You don't have to set default values for your further uses in session flow.

UserOption<double>("font_size" , defaultValue: 10);

Content Controller

You can store or cache your common uses contents.

For example: Friend users, e-commerce categories eg.

Just! you will get content with their identifier.

You don't need a second query from db to recall content repeatedly.

However, if the content is too old, it will be restored from db.

  var controller = UserController();
  await controller.getContent("user_1");
  /// If content was brought before will get from local
  /// else will get from db, save to local and return to you

Usage

Implement CacheAble

Your cache able class must have a unique identifier.

///
class User with CacheAble<User> {
  ///
  User(this.userId, this.userName);
  
  @override
  String get identifier => userId;

  ///
  String userId;

  ///
  String userName;
}

Implement your controller

There are two kind content controller:

  1. CacheContentController : Store contents only session
  2. StorageContentController : Store contents in device key-value storage
///
class UserController extends StorageContentController<User> {
  
  /// Singleton recommended

  /// Getter for your content by identifier
  /// common use this getter get content from db
  @override
  Future<User?> contentGetter(String identifier) async {
    await Future.delayed(const Duration(milliseconds: 300));
    return User(identifier, "User Of $identifier");
  }

  /// DON'T NEED for CacheContentController
  /// NEED for store device storage
  @override
  User fromJson(Map<String, dynamic> map) {
    return User.fromJson(map);
  }

  /// Maximum storage count
  @override
  int get maxCount => 30;

  
  /// Maximum storage duration
  /// If your content older than, recall getter from db
  @override
  Duration get maxDuration => const Duration(minutes: 30);

  /// Save key for local storage
  /// 
  /// DON'T NEED for CacheContentController
  /// NEED for store device storage
  @override
  String get saveKey => "users";

  /// DON'T NEED for CacheContentController
  /// NEED for store device storage
  @override
  Map<String, dynamic> toJson(User instance) {
    return instance.toJson();
  }
}

Also you can inititialize with your unordered contents

controller.init(contents);

Save , update or remove content But many cases you dont need this. Because if you determine max's carefully, getContent do these for you.

controller.save(content);
controller.remove(id);
controller.update(id);

Future

  • VersionedContentController : For versioned contents eg: translations documents
  • Stream to YazNotifier : eg: Database listener to YazNotifier

Support Me: [email protected]

You might also like...

An extension to the bloc state management library which lets you create State Machine using a declarative API

An extension to the bloc state management library which lets you create State Machine using a declarative API

Nov 28, 2022

A powerful state machine for MobX management, that can be used in almost any application state.

A powerful state machine for MobX management, which can be used in almost any application state. It has 3 states - loading, success, error - and is pe

Oct 31, 2022

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package. Built after react apollo

Flutter GraphQL Table of Contents Flutter GraphQL Table of Contents About this project Installation Usage GraphQL Provider [Graphql Link and Headers]

Nov 9, 2022

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.

GraphQL Flutter 📌 Bulletin See the v3 - v4 Migration Guide if you're still on v3. Maintenance status: Low. Follow #762 for updates on the planned ar

Jan 5, 2023

Vrchat mobile client - VRChat Unofficial Mobile Client For Flutter

Vrchat mobile client - VRChat Unofficial Mobile Client For Flutter

VRChatMC VRChatの非公式なAPIを利用したVRChatのモバイルクライアント Flutterで作成されたシンプルなUIが特徴的です iosビルドは

Sep 28, 2022

An app for small and medium organizations (SME) manager, with NFC-tag, e-tag and QR code features supported.

BK LAB Manager - an app for group management 1. Getting Started An app for small and medium organizations (SME) manager, with NFC-tag, e-tag and QR co

Dec 11, 2022

Flutter Download Manager is a Cross-Platform file downloader with Parallel and Batch Download support

Flutter Download Manager is a Cross-Platform file downloader with Parallel and Batch Download support

Flutter Download Manager is a Cross-Platform file downloader with Parallel and Batch Download support. Manage download tasks by url and be notified of status and their progress. Pause, Cancel, Queue and Resume Downloads.

Dec 17, 2022

An easy configurable and secure open-source personal password manager.

An easy configurable and secure open-source personal password manager.

An easy configurable and secure open-source personal password manager. Anyone can you this project and generate his own personal mobile app. All the passwords will be saved into your own Firebase Firestone database with encryption.

Dec 28, 2022

A GUI package manager and package installer for Windows Subsystem for Android (WSA)

A GUI package manager and package installer for Windows Subsystem for Android (WSA)

wsa_pacman A GUI package manager and package installer for Windows Subsystem for Android (WSA). Currently provides a double-click GUI installer for .a

Jan 1, 2023
Releases(0.0.5+7)
Owner
Mehmet Yaz
Flutter developer
Mehmet Yaz
Daily-Task-Manager a daily task manager application project created in flutter

This is a daily task manager application project created in flutter. Install this application on Android - Install from Play Store

DVS 0 May 10, 2022
Kyber Mod Manager A Mod Manager build for Kyber.

Kyber Mod Manager A Mod Manager build for Kyber. This app is not affiliated with Kyber or any of its creators. Key Features • Download • Screenshots •

liam 14 Sep 25, 2022
Flutter Task Manager Application Using GetX State Management

Flutter Task Manager Application Using GetX State Management flutter_getx_todo A new Flutter project. Getting Started This project is a starting point

Siddharth Parekh 5 Nov 11, 2022
Student manager app whith state mannagement approch bloc.

bloc_student_manager A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you sta

Ajay s u 11 Aug 3, 2022
Rooftop - A photos and videos application which is able to show curated content from Pexel database on the press of a button

rooftop RoofTop is a photos and videos application which is able to show curated

null 2 Feb 7, 2022
A library for widgets that load their content one page (or batch) at a time.

A library for widgets that load their content one page (or batch) at a time (also known as lazy-loading and pagination). Features Load data one page a

null 224 Oct 20, 2022
Repository with the content for my book about dart

Informações do livro em dartguide.dev Sumário completo Página do livro na Casa do Código Neste repositório você encontrará todos os códigos de exemplo

null 59 Dec 29, 2022
Practice building basic animations in apps along with managing app state by BLoC State Management, Flutter Slider.

Practice building basic animations in apps along with managing app state by BLoC State Management including: Cubit & Animation Widget, Flutter Slider.

TAD 1 Jun 8, 2022