搜尋套件、儲存庫與 APP 分類

套件詳情v0.0.5

sprinkle

一種便利的基於流的 Flutter 架構

近 30 天下載
15
喜歡數
17
Pub 分數
10

安裝套件

flutter pub add sprinkle

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

Sprinkle 是一種基於流的 Flutter 架構,旨在實現簡潔與可擴展性。它透過流利用反應式程式設計來管理狀態與相依性,從而實現應用程式中高效資料流。Sprinkle 採用清晰的關注點分離,透過將業務邏輯與 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 項

原始碼儲存庫

使用此套件的專案

暫無相關資料。