Skip to content

Commit

Permalink
feat: update transform and combine
Browse files Browse the repository at this point in the history
  • Loading branch information
minhnnGuide committed Feb 22, 2024
1 parent e22ced9 commit 0dfaffc
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 259 deletions.
4 changes: 2 additions & 2 deletions example/lib/ui/home/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class MyHomePage extends ConsumerViewModelWidget<HomePageViewModel> {
appBar: AppBar(
title: const Text("Home"),
),
body: Center(
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
children: <Widget>[
Text('Hi there:'),
],
),
Expand Down
2 changes: 1 addition & 1 deletion packages/maac_mvvm/lib/src/ui/stream_data_consumer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ class StreamDataConsumer<Data> extends StatelessWidget {
},
);
}
}
}
52 changes: 49 additions & 3 deletions packages/maac_mvvm/lib/src/view_model/stream_data/stream_data.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:async';

import 'package:async/async.dart';
import 'package:maac_mvvm/src/view_model/view_model.dart';
import 'package:maac_mvvm/src/view_model/view_model_life_cycle.dart';

/// A StreamData class used when updating data state from ViewModel to Widget.
///
Expand Down Expand Up @@ -75,19 +77,23 @@ abstract class StreamData<T> {
/// }
/// }
///```
class StreamDataViewModel<T> extends StreamData<T> {
class StreamDataViewModel<T> extends StreamData<T> with ViewModelLifecycle {
late final ViewModel _viewModel;
StreamDataViewModel({
required super.defaultValue,
required ViewModel viewModel,
}) {
viewModel.addStreamData(this);
_viewModel = viewModel;
viewModel.addComponents(this);
}

final StreamController<T> _controller = StreamController.broadcast();

Sink<T> get _sink => _controller.sink;

Stream<T> get _stream => _controller.stream;
final List<StreamSubscription> _sourcesSub = [];


/// Update [data] while notifying the Widget or listener of the update via stream.
void postValue(T data) {
Expand All @@ -105,7 +111,14 @@ class StreamDataViewModel<T> extends StreamData<T> {
@override
Stream<T> asStream() => _stream;

void close() => _controller.close();
@override
void onDispose() {
_controller.close();
for (var element in _sourcesSub) {
element.cancel();
}
super.onDispose();
}

Future<bool> any(bool Function(T element) test) {
return _stream.any(test);
Expand All @@ -117,4 +130,37 @@ class StreamDataViewModel<T> extends StreamData<T> {
}) {
return _stream.asBroadcastStream(onListen: onListen, onCancel: onCancel);
}

StreamData<R> map<R>({
required R Function(T data) mapper,
}) {
final stream = this.asStream();
final mapperStream = stream.map((event) => mapper(event));
final mapMutableData = StreamDataViewModel(defaultValue: mapper(_data), viewModel: _viewModel);
_sourcesSub.add(mapperStream.listen((event) => mapMutableData.postValue(event)));
return mapMutableData;
}
}

class MediatorStreamData<T> extends StreamDataViewModel<T> {
final List<StreamSubscription> _sourcesSub = [];

MediatorStreamData({
required super.defaultValue,
required ViewModel viewModel,
}) : super(viewModel: viewModel) {
viewModel.addComponents(this);
}

void addSource<G>(Stream<G> source, void Function(G data) onData) {
_sourcesSub.add(source.listen((event) => onData(event)));
}

@override
void onDispose() {
for (var element in _sourcesSub) {
element.cancel();
}
super.onDispose();
}
}
21 changes: 14 additions & 7 deletions packages/maac_mvvm/lib/src/view_model/view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@ import 'package:maac_mvvm/src/view_model/view_model_life_cycle.dart';
///
///Please refer to [ViewModelLifecycle] for more information.
abstract class ViewModel extends ViewModelLifecycle {
final List<StreamDataViewModel> _listStreamData = <StreamDataViewModel>[];
final List<ViewModelLifecycle> _listLifeComponents = <ViewModelLifecycle>[];
final Map<Key, CancelableOperation> _cancelableOperation = HashMap();

@override
void onInitState() {
_initStateComponent();
markViewModelHasBondLifeCycle();
super.onInitState();
}

@override
void onDispose() {
_cancelViewModelScope();
_closeStreamData();
_disposeComponent();
super.onDispose();
}

Expand Down Expand Up @@ -58,13 +59,13 @@ abstract class ViewModel extends ViewModelLifecycle {
}
}

void addStreamData(StreamDataViewModel streamDataViewModel) {
_listStreamData.add(streamDataViewModel);
void addComponents(ViewModelLifecycle lifecycleComponent) {
_listLifeComponents.add(lifecycleComponent);
}

void _closeStreamData() {
for (var element in _listStreamData) {
element.close();
void _disposeComponent() {
for (var element in _listLifeComponents) {
element.onDispose();
}
}

Expand All @@ -74,4 +75,10 @@ abstract class ViewModel extends ViewModelLifecycle {
void markViewModelHasBondLifeCycle() {
_isBoundLifeCycle = true;
}

void _initStateComponent() {
for (var element in _listLifeComponents) {
element.onInitState();
}
}
}
19 changes: 14 additions & 5 deletions packages/maac_mvvm_with_get_it/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,21 @@ class ExampleAPage extends DependencyViewModelWidget<ExampleAPageViewModel> {
StreamDataConsumer(
builder: (context, data) {
return Text(
'$data',
"$data",
style: Theme.of(context).textTheme.headlineMedium,
);
},
streamData: viewModel.uiState,
),
StreamDataConsumer(
builder: (context, data) {
return Text(
data,
style: Theme.of(context).textTheme.headlineMedium,
);
},
streamData: viewModel.uiStateMap,
),
],
),
),
Expand Down Expand Up @@ -165,13 +174,13 @@ class ExamplePageViewModel extends ViewModel {
}

class ExampleAPageViewModel extends ViewModel {
late final StreamDataViewModel<int> _uiState = StreamDataViewModel(
defaultValue: 0,
viewModel: this,
);
late final _uiState = 0.mutableData(this);

StreamData<int> get uiState => _uiState;

StreamData<String> get uiStateMap =>
_uiState.map(mapper: (data) => "${data + 3}");

void incrementCounter() {
_uiState.postValue(_uiState.data + 1);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/maac_mvvm_with_get_it/example/test/widget_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
Expand Down Expand Up @@ -47,3 +48,4 @@ void main() {
expect(find.text('1'), findsOneWidget);
});
}
*/
Loading

0 comments on commit 0dfaffc

Please sign in to comment.