mavix 0.1.3
mavix: ^0.1.3 copied to clipboard
A lightweight Flutter state manager with separate streams for persistent state and one-time UI activities.
import 'package:flutter/material.dart';
import 'package:mavix/mavix.dart';
void main() {
runApp(const ExampleApp());
}
class CounterMavix extends Mavix<CounterState, CounterActivity> {
CounterMavix() : super(const CounterState());
void increment() {
final nextCount = state.count + 1;
update(state.copyWith(count: nextCount));
if (nextCount % 5 == 0) {
send(MilestoneReached(nextCount));
}
}
void reset() {
if (state.count == 0) {
return;
}
update(const CounterState());
send(const CounterReset());
}
}
class CounterState {
const CounterState({this.count = 0});
final int count;
CounterState copyWith({int? count}) {
return CounterState(count: count ?? this.count);
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
other is CounterState && count == other.count;
}
@override
int get hashCode => count.hashCode;
}
sealed class CounterActivity {
const CounterActivity();
}
final class MilestoneReached extends CounterActivity {
const MilestoneReached(this.value);
final int value;
}
final class CounterReset extends CounterActivity {
const CounterReset();
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Mavix Example',
home: MavixProvider<CounterMavix>(
create: (_) => CounterMavix(),
child: const CounterScreen(),
),
);
}
}
class CounterScreen extends StatelessWidget {
const CounterScreen({super.key});
@override
Widget build(BuildContext context) {
return MavixListener<CounterMavix, CounterActivity>(
listener: (context, activity) {
switch (activity) {
case MilestoneReached(:final value):
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('You reached $value taps')));
case CounterReset():
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('Counter reset')));
}
},
child: Scaffold(
appBar: AppBar(title: const Text('Mavix Counter')),
body: Center(
child: MavixSelector<CounterMavix, CounterState, int>(
selector: (state) => state.count,
builder: (context, count) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'$count',
style: Theme.of(context).textTheme.displayMedium,
),
const SizedBox(height: 24),
Wrap(
spacing: 12,
children: [
FilledButton(
onPressed: () {
context.mavix<CounterMavix>().increment();
},
child: const Text('Increment'),
),
OutlinedButton(
onPressed: count == 0
? null
: () {
context.mavix<CounterMavix>().reset();
},
child: const Text('Reset'),
),
],
),
],
);
},
),
),
),
);
}
}