パッケージ、リポジトリ、アプリカテゴリを検索

パッケージ詳細v0.0.5

sprinkle

便利なストリームベースのFlutterアーキテクチャ

30日間ダウンロード
15
いいね数
17
Pub ポイント
10

パッケージをインストール

flutter pub add sprinkle

パッケージ概要

公開情報に基づく選定ガイドです。参考としてご利用ください。

Sprinkle は、シンプルさとスケーラビリティを目的としたストリームベースの Flutter アーキテクチャです。ストリームを通じたリアクティブプログラミングを使用して、状態と依存関係を管理し、アプリ全体で効率的なデータフローを実現します。クリアな責任分離を採用しており、ビジネスロジックをUIコンポーネントから分離することで、テスト可能性と保守性を高めます。Flutterのウィジェットツリーにシームレスに統合され、依存性のインジェクションもサポートしているため、中規模から大規模なアプリに最適です。最小限のボイラープレートと直感的なパターンにより、開発者の体験を重視しています。

用途

  • リアクティブUIの更新
  • 複雑なアプリにおける状態管理
  • Flutter における依存性の注入
  • ストリーム駆動型のデータフロー
  • テストおよびデバッグワークフロー

主な機能

  • ストリームベースの状態管理
  • 組み込みの依存性注入
  • 最小限のボイラープレート
  • テスト可能なアーキテクチャ
  • 関心事の明確な分離

適している対象

  • 中規模から大規模なFlutterプロジェクト
  • リアクティブパターンを求める開発者
  • 保守性を重視するチーム
  • スケーラブルな状態ソリューションを必要とするアプリ
  • テスト性を重視するプロジェクト

注意事項

  • ストリームの理解が必要です
  • 初心者向けの学習曲線
  • 他の代替品と比べてドキュメントが限られている
  • 非常にシンプルなアプリには適していない
  • 高度な機能を利用するには追加の設定が必要になる場合があります

元の README

関連するソースリポジトリの README 原文のスナップショットです。最新の内容はリポジトリをご覧ください。

sprinkle

A convenient Flutter architecture for happy programmers

Getting Started

Overview

State Management

Sprinkle is based on streams. Streams are one of the core mechanics in Dart and in Flutter. Whether you are interacting with your database (e.g. Firebase) or trying to control the order and timing of requests sent to an API, streams are the most natural solution for these scenarios - we could say that streams are idiomatic in Flutter.

Why don't we use streams everywhere for simplicity and coherence then?! Streams are considered difficult, but that reputation is slightly exaggerated. Once you understand the benefits, there is no coming back to traditional state management approaches. And Sprinkle simplifies stream complexities - it's an easy to understand and coherent solution for state management in Flutter.

Reactive

Start by creating a Manager. It's a class that manages one or many data stores. It also exposes actions as methods to change the state in these data stores.

class CounterManager extends Manager {
  // 1. we create a data store (it's just a stream underneath)
  // Managers are immutable, thus stores must be `final`
  final counter = 0.reactive

  // 2. we define some actions
  void increment() => counter.value++;
  void decrement() => counter.value--;
  void add(int number) => counter.value += number;
}

Somewhere in the widget tree, inside the build method we can ask for a specific Manager by using the use method of the BuildContext

class Counter extends StatelessWidget { // Our widgets are *always* stateless
  @override
  Widget build(BuildContext context) {
    // 3. we include a manager with `use`
    var manager = context.use<CounterManager>();

    return Center(
      // 4. we observe a part of widget tree
      child: Observer<int>(
        // 5. we listen to a specific stream from the manager
        stream: manager.counter,
        // 6. we rebuild once the stream changes
        builder: (context, value) => Text("Counter: $value"),
      ),
    );
  }
}

Reactivity is enabled for the following types in Dart:

bool
final value = false.reactive;
int
final value = 42.reactive;
String
final value = 'The quick brown fox jumps over the lazy dog'.reactive;
List
final value = <String>[].reactive
Automatic Provider Setup

Use the Sprinkle widget to split the responsibilities and reduce the boilerplate so that you can write this:

final supervisor = Supervisor()
  .register<AManager>(() => AManager())

void main() => runApp(Sprinkle(supervisor: supervisor, child: App()));

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ...
    )
  }
}

instead of this:

void main() => runApp(EmailApp());

class EmailApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Provider(
      data: Supervisor()
          .register<AManager>(() => AManager())
      child: MaterialApp(
        ...
      ),
    );
  }
}

Manager asks another Manager for help

In this example LoginManager asks for AuthManager. This goes through Supervisor and the requested manager is either provided as-is or instantiated.

class LoginManager extends Manager {
   void logout() {
     var manager = use<AuthManager>()

     manager.setAuthState(AuthState.loggedOut);
   }

   @override
   void dispose() {}
 }
Convenience Methods

Some convenience methods that follow the Pareto principle, i.e. Sprinkle makes aliases for the most common code scenarios.

Navigation

To change routes, you can write

context.display(AnotherPage())

instead of

Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => AnotherPage()),
);
SnackBar

To display a snackbar, you can write:

context.showSnackBar("...you text");

instead of

Scaffold.of(context).showSnackBar(
  SnackBar(content: Text('Yay! A SnackBar!'))
);
mediaQuerySize

to get MediaQuery Size, you can write:

context.mediaQuerySize

instead of


MediaQuery.of(context).size

orientation

to get Device orientation, you can write:

context.orientation

instead of


MediaQuery.of(context).orientation

isLandscape

to check if Device orientation is Landscape, you can write:

context.isLandscape

instead of


MediaQuery.of(context).orientation == Orientation.landscape

isPortrait

to check if Device orientation is Portrait, you can write:

context.isPortrait

instead of


MediaQuery.of(context).orientation == Orientation.portrait

Padding

Use .padding() method on widgets directly

Column(
  children: [
    Text("User 1").padding(8),
    Text("User 2").padding(8),
  ],
);

instead of wrapping them with Padding:

Column(
  children: [
    Padding(
      padding: EdgeInsets.all(8.0),
      child: Text("User 1"),
    ),
    Padding(
      padding: EdgeInsets.all(8.0),
      child: Text("User 2"),
    ),
  ],
);
Center

Use .center() method on widgets directly

Column(
  children: [

  ],
).center();

instead of wrapping them with Center:

Center(
  child:Column(
    children: [

    ],
)
);

カテゴリー

依存関係

依存関係一覧 1 件

ソースリポジトリ

このパッケージを使用しているプロジェクト

データはまだありません。