From ea863c3a41cdde47dda94245d1678b6c5ac94900 Mon Sep 17 00:00:00 2001 From: Marcel Ploch Date: Thu, 22 Feb 2024 10:32:36 +0100 Subject: [PATCH] Adding pages screens repository with state managment --- lib/data/counter/counter.repository.dart | 40 +++++ lib/data/counter/counter.repository.g.dart | 27 ++++ lib/main.dart | 3 +- lib/presentation/app.dart | 7 +- .../counter/counter.bloc.screen.dart | 63 ++++++++ .../counter/counter.riverpod.screen.dart | 48 ++++++ pubspec.lock | 145 ++++++++++++++++++ pubspec.yaml | 8 + 8 files changed, 336 insertions(+), 5 deletions(-) create mode 100644 lib/data/counter/counter.repository.g.dart create mode 100644 lib/presentation/counter/counter.bloc.screen.dart create mode 100644 lib/presentation/counter/counter.riverpod.screen.dart diff --git a/lib/data/counter/counter.repository.dart b/lib/data/counter/counter.repository.dart index bb09a81..1195117 100644 --- a/lib/data/counter/counter.repository.dart +++ b/lib/data/counter/counter.repository.dart @@ -1,6 +1,46 @@ +import 'package:bloc/bloc.dart'; import 'package:counter/data/counter/data_source/api/counter.api.dart'; import 'package:counter/data/counter/data_source/db/counter.db.dart'; import 'package:counter/domain/counter/model/counter.entity.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'counter.repository.g.dart'; + +@riverpod +class CounterRiverpodController extends _$CounterRiverpodController { + @override + Future build() { + return Future.value(CounterEntity(value: 0)); + } + + Future increment() async { + CounterEntity currentValue = state.value!; + state = const AsyncLoading(); + await Future.delayed(const Duration(seconds: 2)); + currentValue = currentValue.copyWith(value: currentValue.value + 1); + if (currentValue.value > 5) { + state = AsyncError('Level top high', StackTrace.fromString('')); + } else { + state = AsyncData(currentValue); + } + } + + Future reset() async { + ref.invalidate(counterRiverpodControllerProvider); + } +} + +class CounterRepositoryCubit extends Cubit { + CounterRepositoryCubit(super.initialState); + + Future increment() async { + await Future.delayed(const Duration(seconds: 3), () { + CounterEntity currentCounter = state; + currentCounter = currentCounter.copyWith(value: currentCounter.value + 1); + emit(currentCounter); + }); + } +} class CounterRepository { final CounterApi counterApi; diff --git a/lib/data/counter/counter.repository.g.dart b/lib/data/counter/counter.repository.g.dart new file mode 100644 index 0000000..aff96a3 --- /dev/null +++ b/lib/data/counter/counter.repository.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'counter.repository.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$counterRiverpodControllerHash() => + r'27a1bfaf638dc4dc3259240f940d52f9037484e8'; + +/// See also [CounterRiverpodController]. +@ProviderFor(CounterRiverpodController) +final counterRiverpodControllerProvider = AutoDisposeAsyncNotifierProvider< + CounterRiverpodController, CounterEntity>.internal( + CounterRiverpodController.new, + name: r'counterRiverpodControllerProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$counterRiverpodControllerHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$CounterRiverpodController = AutoDisposeAsyncNotifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/main.dart b/lib/main.dart index a925da3..57a5074 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,10 +3,11 @@ import 'package:counter/data/counter/data_source/api/counter.api.dart'; import 'package:counter/data/counter/data_source/db/counter.db.dart'; import 'package:counter/presentation/app.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; void main() { final counterRepository = CounterRepository(counterApi: CounterApi(), counterDB: CounterDb()); - runApp(MyApp(counterRepository: counterRepository)); + runApp(ProviderScope(child: MyApp(counterRepository: counterRepository))); } diff --git a/lib/presentation/app.dart b/lib/presentation/app.dart index c946ad1..b0d04e9 100644 --- a/lib/presentation/app.dart +++ b/lib/presentation/app.dart @@ -1,4 +1,6 @@ import 'package:counter/data/counter/counter.repository.dart'; +import 'package:counter/presentation/counter/counter.bloc.screen.dart'; +import 'package:counter/presentation/counter/counter.riverpod.screen.dart'; import 'package:counter/presentation/counter/counter.screen.dart'; import 'package:flutter/material.dart'; @@ -16,10 +18,7 @@ class MyApp extends StatelessWidget { appBarTheme: AppBarTheme(color: Theme.of(context).primaryColor), useMaterial3: true, ), - home: CounterPage( - title: 'Flutter Demo Home Page', - counterRepository: counterRepository, - ), + home: CounterRiverpodScreen(), ); } } diff --git a/lib/presentation/counter/counter.bloc.screen.dart b/lib/presentation/counter/counter.bloc.screen.dart new file mode 100644 index 0000000..0080321 --- /dev/null +++ b/lib/presentation/counter/counter.bloc.screen.dart @@ -0,0 +1,63 @@ +import 'package:counter/data/counter/counter.repository.dart'; +import 'package:counter/domain/counter/model/counter.entity.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class CounterBLocPageScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => CounterRepositoryCubit(CounterEntity(value: 0)), + child: CounterBlocView(), + ); + } +} + +class CounterBlocView extends StatefulWidget { + @override + State createState() => _CounterBlocViewState(); +} + +class _CounterBlocViewState extends State { + bool isLoading = false; + + @override + Widget build(BuildContext context) { + final counterRepository = context.watch(); + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: Text('Counter Bloc'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + isLoading + ? CircularProgressIndicator() + : Text( + '${counterRepository.state.value}', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () async { + isLoading = true; + setState(() {}); + await counterRepository.increment(); + isLoading = false; + setState(() {}); + + ///close overlay + }, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), + ); + } +} diff --git a/lib/presentation/counter/counter.riverpod.screen.dart b/lib/presentation/counter/counter.riverpod.screen.dart new file mode 100644 index 0000000..04bb036 --- /dev/null +++ b/lib/presentation/counter/counter.riverpod.screen.dart @@ -0,0 +1,48 @@ +import 'package:counter/data/counter/counter.repository.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class CounterRiverpodScreen extends ConsumerWidget { + @override + Widget build(BuildContext context, WidgetRef ref) { + final counterController = ref.watch(counterRiverpodControllerProvider); + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: const Text('Riverpod Screen'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + counterController.when( + data: (data) { + return Text( + '${data.value}', + style: Theme.of(context).textTheme.headlineMedium, + ); + }, + loading: () => const Center( + child: CircularProgressIndicator(), + ), + error: (error, __) { + return Text(error.toString()); + }, + ) + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + ref.read(counterRiverpodControllerProvider.notifier).increment(); + }, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 721cc4c..1228279 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.4.1" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161" + url: "https://pub.dev" + source: hosted + version: "0.11.3" args: dependency: transitive description: @@ -33,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + bloc: + dependency: "direct main" + description: + name: bloc + sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e + url: "https://pub.dev" + source: hosted + version: "8.1.3" boolean_selector: dependency: transitive description: @@ -121,6 +137,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + ci: + dependency: transitive + description: + name: ci + sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13" + url: "https://pub.dev" + source: hosted + version: "0.1.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + url: "https://pub.dev" + source: hosted + version: "0.4.1" clock: dependency: transitive description: @@ -169,6 +201,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + custom_lint: + dependency: transitive + description: + name: custom_lint + sha256: "445242371d91d2e24bd7b82e3583a2c05610094ba2d0575262484ad889c8f981" + url: "https://pub.dev" + source: hosted + version: "0.6.2" + custom_lint_core: + dependency: transitive + description: + name: custom_lint_core + sha256: ce5d6215f4e143f7780ce53f73dfa6fc503f39d2d30bef76c48be9ac1a09d9a6 + url: "https://pub.dev" + source: hosted + version: "0.6.2" dart_style: dependency: transitive description: @@ -206,6 +254,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1" + url: "https://pub.dev" + source: hosted + version: "8.1.4" flutter_lints: dependency: "direct dev" description: @@ -214,6 +270,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "4bce556b7ecbfea26109638d5237684538d4abc509d253e6c5c4c5733b360098" + url: "https://pub.dev" + source: hosted + version: "2.4.10" flutter_test: dependency: "direct dev" description: flutter @@ -387,6 +451,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.3" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" package_config: dependency: transitive description: @@ -411,6 +483,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + provider: + dependency: transitive + description: + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + url: "https://pub.dev" + source: hosted + version: "6.1.1" pub_semver: dependency: transitive description: @@ -427,6 +507,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.3" + riverpod: + dependency: transitive + description: + name: riverpod + sha256: "548e2192eb7aeb826eb89387f814edb76594f3363e2c0bb99dd733d795ba3589" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + riverpod_analyzer_utils: + dependency: transitive + description: + name: riverpod_analyzer_utils + sha256: "8b71f03fc47ae27d13769496a1746332df4cec43918aeba9aff1e232783a780f" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + riverpod_annotation: + dependency: "direct main" + description: + name: riverpod_annotation + sha256: "77e5d51afa4fa3e67903fb8746f33d368728d7051a0b6c292bcee60aeba46d95" + url: "https://pub.dev" + source: hosted + version: "2.3.4" + riverpod_generator: + dependency: "direct dev" + description: + name: riverpod_generator + sha256: "359068f04879347ae4edbe66c81cc95f83fa1743806d1a0c86e55dd3c33ebb32" + url: "https://pub.dev" + source: hosted + version: "2.3.11" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" shelf: dependency: transitive description: @@ -472,6 +592,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: @@ -480,6 +608,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.11.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" stream_channel: dependency: transitive description: @@ -536,6 +672,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 + url: "https://pub.dev" + source: hosted + version: "4.3.3" vector_math: dependency: transitive description: @@ -586,3 +730,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.3.0 <4.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 28f755d..956d2db 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,9 +8,17 @@ dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.6 + freezed_annotation: ^2.4.1 json_annotation: ^4.8.1 + flutter_riverpod: ^2.3.9 + riverpod_annotation: ^2.1.3 + + bloc: ^8.1.0 + flutter_bloc: ^8.1.1 dev_dependencies: + + riverpod_generator: ^2.3.0 freezed: ^2.4.7 flutter_test: sdk: flutter