application_layers_framework 1.0.1
application_layers_framework: ^1.0.1 copied to clipboard
A framework to standardize the implementation of a Flutter application by separating the application logic into different layers.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:application_layers_framework/application_layers_framework.dart';
void main() {
runApp(RootPage());
}
class CounterEntity extends ALFEntity {
int counter = 0;
}
class CounterRepository extends ALFRepository {
CounterEntity counterEntity = CounterEntity();
void increment(int delta) {
counterEntity.counter = counterEntity.counter + delta;
notify();
}
void decrement(int delta) {
counterEntity.counter = counterEntity.counter - delta;
notify();
}
}
class RootController extends ALFWidgetController {}
class RootPage extends ALFWidgetView {
RootPage({super.key})
: super(controller: RootController(), repositories: [ALFRepositoryProvider<CounterRepository>(create: (context) => CounterRepository())]);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true),
home: HomePage(title: "Flutter Demo Home Page"),
);
}
}
enum HomeEvent { refresh, gotoCounter }
class HomeController extends ALFWidgetController {
HomeController() {
register(event: HomeEvent.refresh, trigger: refreshView);
register(event: HomeEvent.gotoCounter, trigger: gotoCounter);
}
void gotoCounter({dynamic params}) {
CounterPage page = CounterPage();
Navigator.push(context, MaterialPageRoute(builder: (context) => page));
}
@override
void init() {
subscribeRepository<CounterRepository>(event: HomeEvent.refresh);
}
}
class HomePage extends ALFWidgetView {
final String title;
HomePage({required this.title, super.key}) : super(controller: HomeController());
@override
Widget build(BuildContext context) {
CounterRepository counterRepository = repo<CounterRepository>();
return Scaffold(
appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("The counter is currently at:"),
Text('${counterRepository.counterEntity.counter}', style: Theme.of(context).textTheme.headlineMedium),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => trigger(event: HomeEvent.gotoCounter),
tooltip: "Go to counter",
child: const Icon(Icons.arrow_circle_right),
),
);
}
}
enum CounterEvent { changeBackgroundColor, incrementDelta, decrementDelta, incrementCounter, decrementCounter }
enum CounterState { backgroundColor, delta }
class CounterController extends ALFWidgetController {
CounterController() : super(state: {CounterState.backgroundColor: Colors.white, CounterState.delta: 1}) {
register(event: CounterEvent.changeBackgroundColor, trigger: changeBackgroundColor);
register(event: CounterEvent.incrementDelta, trigger: incrementDelta);
register(event: CounterEvent.decrementDelta, trigger: decrementDelta);
register(event: CounterEvent.incrementCounter, trigger: incrementCounter);
register(event: CounterEvent.decrementCounter, trigger: decrementCounter);
}
void changeBackgroundColor({dynamic params}) {
update(state: {CounterState.backgroundColor: params});
}
void incrementDelta({dynamic params}) {
update(state: {CounterState.delta: state[CounterState.delta] + 1});
}
void decrementDelta({dynamic params}) {
update(state: {CounterState.delta: state[CounterState.delta] - 1});
}
void incrementCounter({dynamic params}) {
CounterRepository counterRepository = repo<CounterRepository>();
counterRepository.increment(state[CounterState.delta]);
refreshView();
}
void decrementCounter({dynamic params}) {
CounterRepository counterRepository = repo<CounterRepository>();
counterRepository.decrement(state[CounterState.delta]);
refreshView();
}
}
class CounterPage extends ALFWidgetView {
CounterPage({super.key}) : super(controller: CounterController());
@override
Widget build(BuildContext context) {
CounterRepository counterRepository = repo<CounterRepository>();
return Scaffold(
backgroundColor: state[CounterState.backgroundColor],
appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text("Flutter Demo Counter Page")),
body: Center(
child: SizedBox(
width: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ListTile(
title: Text("White color"),
leading: Radio<Color>(
value: Colors.white,
groupValue: state[CounterState.backgroundColor],
onChanged: (Color? value) => trigger(event: CounterEvent.changeBackgroundColor, params: value!),
),
),
ListTile(
title: Text("Blue color"),
leading: Radio<Color>(
value: Colors.blue,
groupValue: state[CounterState.backgroundColor],
onChanged: (Color? value) => trigger(event: CounterEvent.changeBackgroundColor, params: value!),
),
),
ListTile(
title: Text("Green color"),
leading: Radio<Color>(
value: Colors.green,
groupValue: state[CounterState.backgroundColor],
onChanged: (Color? value) => trigger(event: CounterEvent.changeBackgroundColor, params: value!),
),
),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(onPressed: () => trigger(event: CounterEvent.decrementCounter), child: const Icon(Icons.remove)),
const SizedBox(width: 10),
Text("Counter value: ${counterRepository.counterEntity.counter}"),
const SizedBox(width: 10),
ElevatedButton(onPressed: () => trigger(event: CounterEvent.incrementCounter), child: const Icon(Icons.add)),
],
),
const SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: state[CounterState.delta] <= 1 ? null : () => trigger(event: CounterEvent.decrementDelta),
child: const Icon(Icons.remove),
),
const SizedBox(width: 10),
Text("Delta value: ${state[CounterState.delta]}"),
const SizedBox(width: 10),
ElevatedButton(onPressed: () => trigger(event: CounterEvent.incrementDelta), child: const Icon(Icons.add)),
],
),
],
),
),
),
);
}
}