Skip to content

Instantly share code, notes, and snippets.

@saad-palapa
Last active March 29, 2023 20:23
Show Gist options
  • Save saad-palapa/f2eaa8c45e239aced25f2bddbee6da44 to your computer and use it in GitHub Desktop.
Save saad-palapa/f2eaa8c45e239aced25f2bddbee6da44 to your computer and use it in GitHub Desktop.
Custom flutter state management by wrapping 3rd party state management libraries
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// this is an interface to a state management library
// clients of this library should not depend on any specific state management library
class Published<T> {
final _CubitWrapper<T> _cubit;
Published(T val) : _cubit = _CubitWrapper(val);
T get val => _cubit.state;
set val(T newVal) => _cubit.update(newVal);
Future<void> close() => _cubit.close();
}
// this class is needed because Cubit.emit() is @protected
class _CubitWrapper<T> extends Cubit<T> {
_CubitWrapper(T state) : super(state);
void update(T newVal) => emit(newVal);
@override
Future<void> close() async {
print("Closing cubit, state=$state");
return super.close();
}
}
class PublishedConsumer<T> extends BlocConsumer<_CubitWrapper<T>, T> {
PublishedConsumer._({
required Published<T> published,
required Widget Function(BuildContext, T) builder,
required void Function(BuildContext, T) listener,
}) : super(bloc: published._cubit, builder: builder, listener: listener);
factory PublishedConsumer.withContext({
required Published<T> published,
Widget Function(BuildContext, T)? builder,
void Function(BuildContext, T)? listener,
}) {
return PublishedConsumer._(
published: published,
builder: builder ?? (_, __) => Container(),
listener: listener ?? (_, __) => null,
);
}
factory PublishedConsumer.new({
required Published<T> published,
Widget Function(T)? builder,
void Function(T)? listener,
}) {
return PublishedConsumer._(
published: published,
builder: builder == null ? (_, __) => Container() : (_, v) => builder(v),
listener: listener == null ? (_, __) => null : (_, v) => listener(v),
);
}
}
// sample implementation
class LibraryScreen extends View<LibraryPage> {
LibraryScreen() : super(LibraryPage());
LibraryPage get page => viewModel;
@override
Widget build(BuildContext context) {
return Column(
children: [
ChipWheel(LibraryChips.values, onSelect: page.chipTapped),
Expanded(
child: PublishedConsumer(
published: page.chip,
builder: (_) => Text(page.chip.name),
),
),
],
);
}
}
class LibraryPage extends ViewModel {
final chip = Published(LibraryChips.all);
LibraryPage();
void chipTapped(LibraryChips chip) => this.chip.val = chip;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment