zenify 1.3.5 copy "zenify: ^1.3.5" to clipboard
zenify: ^1.3.5 copied to clipboard

Powerful asynchronous state management, automatic caching, hierarchical DI, and zero-boilerplate reactivity. A holistic architecture for modern Flutter apps.

Zenify #

pub package likes pub points license: MIT

Complete state management for Flutterβ€”hierarchical dependency injection, reactive programming, and intelligent async state. Zero boilerplate, automatic cleanup.

// Hierarchical DI with automatic cleanup
scope.put<UserService>(UserService());
final service = scope.find<UserService>()!;  // Access from child scopes

// Reactive state that just works
final count = 0.obs();
Obx(() => Text('$count'))  // Auto-rebuilds

// Smart async with caching
final userQuery = ZenQuery<User>(
  queryKey: 'user:123',
  fetcher: (_) => api.getUser(123),
);  // Caching, deduplication, refetchingβ€”all handled

🎯 Why Zenify? #

Building async-heavy Flutter apps? You're probably fighting:

  • πŸ’” Manual cache management - Writing the same cache logic over and over
  • πŸ”„ Duplicate API calls - Multiple widgets fetching the same data
  • πŸ—οΈ Memory leaks - Forgetting to dispose controllers and subscriptions
  • πŸ“¦ Boilerplate overload - Hundreds of lines for simple async state

Zenify solves all of this.


⚑ What Makes Zenify Different #

πŸ—οΈ Hierarchical Scoped Architecture #

Riverpod-inspired scoping with automatic cleanup. Dependencies flow naturally from parent to child, and scopes dispose themselves automatically when no longer needed. Simple API: Zen.put(), Zen.find(), Zen.delete().

🎯 Zero Boilerplate Reactivity #

GetX-like reactive system with .obs() and Obx(). Write less, accomplish more, keep your code clean. Built on Flutter's ValueNotifier for optimal performance.

πŸ”₯ React Query Style #

A native-inspired implementation of TanStack Query patterns: automatic caching, smart refetching, request deduplication, and stale-while-revalidateβ€”built on top of the reactive system.


πŸ—οΈ Understanding Scopes (The Foundation) #

Zenify organizes dependencies into three hierarchical levels with automatic lifecycle management:

The Three Scope Levels #

🌍 RootScope (Global - App Lifetime)

  • Services like AuthService, CartService, ThemeService
  • Lives for entire app session
  • Access anywhere via Zen.find

πŸ“¦ Module Scope (Feature - Feature Lifetime)

  • Controllers shared across feature pages
  • Auto-dispose when leaving feature
  • Example: HR feature with CompanyController β†’ DepartmentController β†’ EmployeeController

πŸ“„ Page Scope (Page - Page Lifetime)

  • Page-specific controllers
  • Auto-dispose when page pops
  • Example: LoginController, ProfileFormController

When to Use What #

Scope Use For Example Lifetime
RootScope Needed across entire app Zen.find<T>() App session
Module Scope Needed across a feature Module registration Feature navigation
Page Scope Needed on one page createController Single page

The scope hierarchy automatically manages lifecycle - when you exit a feature, all its controllers clean up automatically. No memory leaks, no manual disposal.

Learn more about hierarchical scopes β†’


πŸš€ Quick Start (30 seconds) #

1. Install #

dependencies:
  zenify: ^1.3.5

2. Initialize #

void main() {
  Zen.init();
  runApp(MyApp());
}

3. Create a Controller #

class CounterController extends ZenController {
  final count = 0.obs();
  void increment() => count.value++;
}

4. Build UI #

class CounterPage extends ZenView<CounterController> {
  // Correct syntax: getter returning a lambda
  @override
  CounterController Function()? get createController => () => CounterController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Obx(() => Text('Count: ${controller.count.value}')),
            ElevatedButton(
              onPressed: controller.increment,
              child: Text('Increment'),
            ),
          ],
        ),
      ),
    );
  }
}

That's it! Fully reactive with automatic cleanup. No manual disposal, no memory leaks.

Note: createController is optional! If your controller is already registered in a module or globally, you can omit it and ZenView will find the controller automatically.

See complete example β†’


πŸ”₯ Core Features #

1. Hierarchical DI with Auto-Cleanup #

Organize dependencies naturally with feature-based modules and parent-child scopes. When you navigate away, everything cleans up automatically.

// App-level services (persistent)
class AppModule extends ZenModule {
  @override
  void register(ZenScope scope) {
    scope.put<AuthService>(AuthService(), isPermanent: true);
    scope.put<DatabaseService>(DatabaseService(), isPermanent: true);
  }
}

// Feature-level controllers (auto-disposed)
class UserModule extends ZenModule {
  @override
  void register(ZenScope scope) {
    // Access parent services via Zen.find()
    final db = scope.find<DatabaseService>()!;

    // Register feature-specific dependencies
    scope.putLazy<UserRepository>(() => UserRepository(db));
    scope.putLazy<UserController>(() => UserController());
  }
}

// Use with any router - it's just a widget!
ZenRoute(
  moduleBuilder: () => UserModule(),
  page: UserPage(),
  scopeName: 'UserScope',
)

Core API:

  • Zen.put<T>() - Register dependencies
  • Zen.find<T>() - Retrieve dependencies
  • Zen.delete<T>() - Remove dependencies

What you get:

  • πŸ—οΈ Natural dependency flow (parent β†’ child)
  • πŸ”„ Automatic disposal (no memory leaks)
  • πŸ“¦ Clean module organization
  • πŸ§ͺ Easy testing (swap modules)

Works with: GoRouter, AutoRoute, Navigator 2.0, any router you like.

See Hierarchical Scopes Guide β†’

2. Zero-Boilerplate Reactivity #

GetX-inspired reactive system built on Flutter's ValueNotifier. Simple, fast, no magic.

class TodoController extends ZenController {
  // Reactive primitives
  final todos = <Todo>[].obs();
  final filter = Filter.all.obs();

  // Computed values (auto-update)
  List<Todo> get filteredTodos {
    switch (filter.value) {
      case Filter.active: return todos.where((t) => !t.done).toList();
      case Filter.completed: return todos.where((t) => t.done).toList();
      default: return todos.toList();
    }
  }

  // Actions
  void addTodo(String title) => todos.add(Todo(title));
  void toggleTodo(Todo todo) => todo.done = !todo.done;
}

// In UI - automatic rebuilds
Obx(() => Text('${controller.todos.length} todos'))
Obx(() => ListView.builder(
  itemCount: controller.filteredTodos.length,
  itemBuilder: (context, i) => TodoItem(controller.filteredTodos[i]),
))

What you get:

  • ⚑ Minimal rebuilds (only affected widgets)
  • 🎯 Simple API (.obs(), Obx(), done)
  • πŸ”’ Type-safe (compile-time checks)
  • 🏎️ Zero overhead (built on ValueNotifier)

See Reactive Core Guide β†’

3. Smart Async State (ZenQuery) #

React Query patterns built on the reactive system.

// Define once
final userQuery = ZenQuery<User>(
  queryKey: 'user:123',
  fetcher: (_) => api.getUser(123),
  config: ZenQueryConfig(
    staleTime: Duration(minutes: 5),
    cacheTime: Duration(hours: 1),
  ),
);

// Use anywhere - automatic caching, deduplication, refetching
ZenQueryBuilder<User>(
  query: userQuery,
  builder: (context, user) => UserProfile(user),
  loading: () => CircularProgressIndicator(),
  error: (error, retry) => ErrorView(error, onRetry: retry),
);

What you get for free:

  • βœ… Automatic caching with configurable staleness
  • βœ… Smart deduplication (same key = one request)
  • βœ… Background refetch on focus/reconnect
  • βœ… Stale-while-revalidate (show cached, fetch fresh)
  • βœ… Request cancellation (no wasted bandwidth)
  • βœ… Optimistic updates with rollback
  • βœ… Infinite scroll pagination
  • βœ… Real-time streams support

Perfect for: REST APIs, GraphQL, Firebase, any async data source.

See ZenQuery Guide β†’


πŸ’‘ Common Patterns #

Global Services with .to Pattern #

Access services from anywhere without context or injection:

class CartService extends ZenService {
  static CartService get to => Zen.find<CartService>();

  final items = <CartItem>[].obs();

  void addToCart(Product product) {
    items.add(CartItem.fromProduct(product));
  }

  @override
  void onClose() {
    // Cleanup happens automatically
    super.onClose();
  }
}

// Register once
void main() {
  Zen.init();
  Zen.put<CartService>(CartService(), isPermanent: true);
  runApp(MyApp());
}

// Use anywhere - widgets, controllers, helpers
CartService.to.addToCart(product);

Infinite Scroll Pagination #

final postsQuery = ZenInfiniteQuery<PostPage>(
  queryKey: ['posts'],
  infiniteFetcher: (cursor, token) => api.getPosts(cursor: cursor),
);

// Auto-load next page when reaching end
if (index == postsQuery.data.length - 1) postsQuery.fetchNextPage();

Optimistic Updates #

final mutation = ZenMutation<User, UpdateArgs>(
  onMutate: (args) => userQuery.data.value = args.toUser(), // Instant UI
  onError: (err, args, old) => userQuery.data.value = old,  // Rollback
);

Real-Time Streams #

final chatQuery = ZenStreamQuery<List<Message>>(
  queryKey: 'chat',
  streamFn: () => chatService.messagesStream,
);

See complete patterns with detailed examples β†’


πŸ› οΈ Advanced Features #

  • Effects - Automatic loading/error/success state management (guide)
  • Computed Values - Auto-updating derived state with dependency tracking
  • Global Modules - Register app-wide dependencies at startup
  • Performance Control - Choose between reactive (.obs() + Obx) or manual (update() + ZenBuilder)
  • Workers - Debounce, throttle, and interval-based reactive handlers
  • Devtools - Built-in inspector overlay for debugging scopes and queries

See detailed examples β†’


πŸŽ“ Learning Path #

New to Zenify? Start here:

  1. 5 minutes: Counter Example - Basic reactivity
  2. 10 minutes: Todo Example - CRUD with effects
  3. 15 minutes: ZenQuery Guide - Async state management
  4. 20 minutes: E-commerce Example - Real-world patterns

Building something complex?


πŸ“± Widget Quick Reference #

Choose the right widget for your use case:

Widget Use When Rebuilds On
ZenView Building pages with controllers Automatic lifecycle
ZenRoute Need module/scope per route Route navigation
Obx Need reactive updates Reactive value changes
ZenBuilder Need manual control controller.update() call
ZenQueryBuilder Fetching API data Query state changes
ZenStreamQueryBuilder Real-time data streams Stream events
ZenEffectBuilder Async operations Effect state changes
ZenConsumer Accessing dependencies Manual (no auto-rebuild)

90% of the time, you'll use:

  • ZenView for pages
  • Obx for reactive UI
  • ZenQueryBuilder for API calls

πŸ”§ Configuration #

void main() {
  Zen.init();

  // Optional: Configure logging and performance tracking
  ZenConfig.configure(level: ZenLogLevel.info, performanceTracking: true);

  // Optional: Set query defaults
  ZenQueryConfig.defaults = ZenQueryConfig(
    staleTime: Duration(minutes: 5),
    cacheTime: Duration(hours: 1),
  );

  runApp(MyApp());
}

πŸ§ͺ Testing #

Built for testing from the ground up with mocking support:

void main() {
  setUp(() => Zen.testMode().clearQueryCache());
  tearDown(() => Zen.reset());

  test('counter increments', () {
    final controller = CounterController();
    controller.increment();
    expect(controller.count.value, 1);
  });

  test('mock dependencies', () {
    Zen.testMode().mock<ApiClient>(FakeApiClient());
    // Test code uses mock automatically
  });
}

See complete testing guide β†’


πŸ“š Complete Documentation #

Core Guides #

Examples #


πŸ™ Inspired By #

Zenify stands on the shoulders of giants:

  • GetX by Jonny Borges - For intuitive reactive patterns
  • Riverpod by Remi Rousselet - For hierarchical scoping
  • React Query by Tanner Linsley - For smart async state

πŸ’¬ Community & Support #


πŸ“„ License #

MIT License - see LICENSE file


πŸš€ Ready to Get Started? #

# Add to pubspec.yaml
flutter pub add zenify

# Try the examples
cd example/counter && flutter run

Choose your path:

Experience the zen of Flutter development. ✨

3
likes
160
points
312
downloads

Publisher

unverified uploader

Weekly Downloads

Powerful asynchronous state management, automatic caching, hierarchical DI, and zero-boilerplate reactivity. A holistic architecture for modern Flutter apps.

Repository (GitHub)
View/report issues

Topics

#state-management #async-state #caching #dependency-injection #react-query

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on zenify