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

套件詳情v1.0.2

june

June 是一個輕量級且現代的狀態管理庫,專注於提供與 Flutter 原生狀態管理非常相似的模式。

AndroidiOSWebmacOSWindowsLinux
近 30 天下載
173
喜歡數
88
Pub 分數
150

安裝套件

flutter pub add june

套件介紹

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

June 是一個輕量級、現代的 Flutter 狀態管理程式庫,它模擬了 Flutter 原生的狀態管理模式。它強調簡潔與可讀性,讓開發者能以反應式的方式輕鬆管理狀態,而無需撰寫冗長的樣板程式碼。June 以開發者體驗為設計核心,可順暢整合至現有的 Flutter 專案中,並支援所有主要平台。其 API 直覺易用,促進乾淨的程式碼結構與高效更新。June 非常適合尋求一種簡潔但強大替代方案,以取代較複雜狀態解決方案的開發者。

適用情境

  • 簡單的應用狀態管理
  • 反應式 UI 更新
  • 跨平台 Flutter 應用
  • 輕量級狀態解決方案
  • 與現有程式碼庫的輕鬆整合

主要特色

  • 最小化樣板程式碼
  • Flutter 原生模式對齊
  • 反應式狀態更新
  • Platform-agnostic
  • 乾淨、易讀的 API
  • 無外部依賴

適合對象

  • 初學者到中級 Flutter 開發者
  • 小型到中型應用
  • 重視簡潔性的專案
  • 希望快速上手的團隊
  • 針對多個平台的應用程式

使用建議

  • 與更大的庫相比,高級功能有限
  • 不太適合大規模狀態需求
  • 比成熟替代方案的社群支援少
  • 最適合簡單的狀態流轉

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。


     ██╗██╗   ██╗███╗   ██╗███████╗
     ██║██║   ██║████╗  ██║██╔════╝
     ██║██║   ██║██╔██╗ ██║█████╗
██   ██║██║   ██║██║╚██╗██║██╔══╝
╚█████╔╝╚██████╔╝██║ ╚████║███████╗
 ╚════╝  ╚═════╝ ╚═╝  ╚═══╝╚══════╝
Flutter state management that feels like Flutter.

Pub Version Pub Likes Pub Points GitHub Stars

Discord KakaoTalk Docs



The problem with state management today

You learned Flutter. You learned setState. It clicked.
Then you added a library and suddenly you're learning a new framework inside your framework — providers, stores, atoms, streams, reducers.

June refuses to do that.

It gives you shared, reactive state that works exactly like Flutter's own state management — just without the widget tree dependency. That's it.



At a glance

Before June — state trapped in a widget

class _CounterState extends State<Counter> {
  int count = 0;         // 🔒 only this widget
                         //    can touch this

  @override
  Widget build(BuildContext context) {
    return Text('$count');
  }
}

With June — state lives anywhere, rebuilds anything

class CounterVM extends JuneState {
  int count = 0;         // ✅ any widget,
                         //    any file,
}                        //    anywhere
JuneBuilder(
  () => CounterVM(),
  builder: (vm) => Text('${vm.count}'),
)


Why June wins on simplicity

June Provider GetX Bloc
No MaterialApp wrapper needed ✅ ❌ ❌ ❌
No manual initialization ✅ ❌ ✅ ❌
Works with StatelessWidget ✅ ✅ ✅ ✅
Call setState from anywhere ✅ ❌ ✅ ❌
Multiple tagged instances ✅ ❌ ✅ ❌
Per-widget isolated state ✅ ❌ ❌ ❌
Zero new architecture required ✅ ❌ ❌ ❌


Installation

dependencies:
  june: ^1.0.2
flutter pub get


Quick start — 3 steps, 3 minutes

Step 1 — Define your state
class CounterVM extends JuneState {
  int count = 0;
}
Step 2 — Subscribe a widget
JuneBuilder(
  () => CounterVM(),
  builder: (vm) => Text('${vm.count}'),
)
Step 3 — Update from anywhere
June.getState(() => CounterVM())
  ..count++
  ..setState();

No providers. No streams. No boilerplate. setState works the same way it always has — just across the whole app.



Full runnable example

import 'package:flutter/material.dart';
import 'package:june/june.dart';

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

// ─── State ─────────────────────────────────────────────────────────────────

class CounterVM extends JuneState {
  int count = 0;

  void increment() {
    count++;
    setState();
  }
}

// ─── UI ────────────────────────────────────────────────────────────────────

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: JuneBuilder(
            () => CounterVM(),
            builder: (vm) => Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text('You have pushed the button this many times:'),
                Text(
                  '${vm.count}',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
              ],
            ),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => June.getState(() => CounterVM()).increment(),
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}


Patterns

Methods on state

Keep logic next to data. Call it from anywhere.

class CounterVM extends JuneState {
  int count = 0;

  void increment() {
    count++;
    setState();
  }

  void reset() {
    count = 0;
    setState();
  }
}
// From a button, a gesture, a timer — anywhere
June.getState(() => CounterVM()).increment();

Multiple instances with tag

One state class, many independent instances — perfect for list items, cards, feeds.

JuneBuilder(
  () => CounterVM(),
  builder: (vm) => Text('Default: ${vm.count}'),
)

JuneBuilder(
  () => CounterVM(),
  tag: 'card_a',
  builder: (vm) => Text('Card A: ${vm.count}'),
)

JuneBuilder(
  () => CounterVM(),
  tag: 'card_b',
  builder: (vm) => Text('Card B: ${vm.count}'),
)
// Update only card A — other instances are unaffected
June.getState(() => CounterVM(), tag: 'card_a')
  ..count++
  ..setState();

Per-widget local state with global: false

For state that belongs to exactly one widget — not shared globally. Pass your own instance and June won't register it.

class SliderState extends JuneState {
  double value = 0.5;
}
final sliderState = SliderState();

JuneBuilder(
  () => sliderState,
  global: false,
  builder: (s) => Slider(
    value: s.value,
    onChanged: (v) {
      s.value = v;
      s.setState();
    },
  ),
)

Each widget holds its own isolated state. Navigating away and back creates a fresh instance — exactly what you want for forms, sliders, and single-use UI.


Theme toggle

JuneBuilder can wrap MaterialApp itself, rebuilding the entire app on state change.

class ThemeController extends JuneState {
  bool isDark = false;

  void toggle() {
    isDark = !isDark;
    setState();
  }
}
return JuneBuilder(
  () => ThemeController(),
  builder: (c) => MaterialApp(
    theme: ThemeData.light(),
    darkTheme: ThemeData.dark(),
    themeMode: c.isDark ? ThemeMode.dark : ThemeMode.light,
    home: const HomeScreen(),
  ),
);

Async state / HTTP

Call setState() when your data arrives. Works with any Future or Stream.

class UserController extends JuneState {
  User? user;
  bool loading = false;

  Future<void> loadUser(String id) async {
    loading = true;
    setState();

    user = await userRepository.fetch(id);
    loading = false;
    setState();
  }
}
JuneBuilder(
  () => UserController(),
  builder: (c) {
    if (c.loading) return const CircularProgressIndicator();
    if (c.user == null) return const Text('No user loaded');
    return Text('Hello, ${c.user!.name}');
  },
)

Selective rebuilds with id

Trigger only specific JuneBuilder widgets inside a shared state, leaving others untouched.

class FeedState extends JuneState {
  String header = 'Latest';
  List<Post> posts = [];

  void updateHeader(String value) {
    header = value;
    setState('header');          // only rebuilds builders with id: 'header'
  }

  void refreshPosts(List<Post> fresh) {
    posts = fresh;
    setState('posts');           // only rebuilds builders with id: 'posts'
  }
}
// Rebuilds only when 'header' setState is called
JuneBuilder(
  () => FeedState(),
  id: 'header',
  builder: (s) => Text(s.header),
)

// Rebuilds only when 'posts' setState is called
JuneBuilder(
  () => FeedState(),
  id: 'posts',
  builder: (s) => PostList(posts: s.posts),
)


Core API

Symbol Role
JuneState Base class for all state objects. Extend it, add fields and methods, call setState() to rebuild.
JuneBuilder Widget that subscribes to a JuneState and rebuilds when setState() fires.
June.getState() Retrieves (or lazily creates) a global singleton of a state type. Thread-safe, no setup needed.
tag Namespaces multiple global instances of the same type.
id Enables partial rebuilds — only JuneBuilder widgets sharing the same id will rebuild.
global: false Bypasses the global registry. The builder uses your provided instance directly.
tag vs id — when to use which
tag id
Lives on JuneBuilder & June.getState() JuneBuilder & setState()
Purpose Pick which stored instance to use Pick which builders to rebuild
Use when Same state type needed in multiple places independently One shared state, but only some widgets should react to a given change


Migration

0.8.x → 1.0.0

The factory function is now passed as a closure rather than an evaluated instance:

// Before (0.8.x)
June.getState(CounterVM());

// After (1.0.0+)
June.getState(() => CounterVM());


Community

Questions, ideas, or just want to say hi?

Discord KakaoTalk Docs



Acknowledgements

June was shaped by the best ideas in the Flutter ecosystem. Gratitude to the teams and communities behind Provider, GetX, Bloc, and Riverpod, and to Svelte for proving that less really is more.


Made with care for the Flutter community.

所屬分類

原始碼儲存庫

使用此套件的專案

暫無相關資料。