maac_mvvm 0.2.0+1 copy "maac_mvvm: ^0.2.0+1" to clipboard
maac_mvvm: ^0.2.0+1 copied to clipboard

maac_mvvm is a package supporting easy MVVM pattern implementation without any dependency injection wrapping, allowing freedom of choice.

MVVM

maac_mvvm is a package that supports simple implementation of the MVVM pattern. The package doesn't wrap any dependency injection inside. With this, you can choose any framework dependency injection you want. It simply has three components: ViewModel, StreamData and ViewModelWidget.

It's simple, clean, and very easy to implement.

Features #

ViewModelWidget #

A place to build UI widgets that the ViewModel is binding to.

ViewModel #

Automatic handling of ViewModel initialization, resumption, pausing, and disposal.

StreamData #

A wrapper of Stream useful to update UI and automatically cancel in the dispose of the ViewModel lifecycle.

Getting Started #

  • Install from pub: flutter pub add maac_mvvm

Usage #

1 - Install package #

flutter pub add maac_mvvm

2 - Create your ViewModel #

The below ViewModel is a simple ViewModel that hold logic increase counter from widget

class ExamplePageViewModel extends ViewModel {
  ExamplePageViewModel();

  late final _uiState = 0.mutableData(this);
  late final uiState = _uiState.streamData;

  void increaseCounter() {
    _uiState.postValue(_uiState.data + 1);
  }
}

3 - Create your Widget bind's with ViewModel #

The ViewModelWidget will only contain two methods: createViewModel and build.

  • The build method is where you build the interface
  • The createViewModel method is where you initialize the corresponding ViewModel.

We don't need to worry about the other lifecycles of the widget because they will be called automatically corresponding to the ViewModel.

class ExamplePage extends ViewModelWidget<ExamplePageViewModel> {
  const ExamplePage({Key? key}) : super(key: key);

  @override
  ExamplePageViewModel createViewModel(BuildContext context) => ExamplePageViewModel();

  @override
  Widget build(BuildContext context, ExamplePageViewModel viewModel) {
    return BuildYourUiWidget();
  }
}

In case the widget has properties passed in and we need to pass them to the ViewModel, we can override awake.

The awake method will be called immediately after the createViewModel method of ViewModelWidget and before the onInitState method of the ViewModel. This will be helpful for setting up the necessary data.

class ExamplePage extends ViewModelWidget<ExamplePageViewModel> {
  final int initValue;
  const ExamplePage({super.key, required this.initValue});

  @override
  ExamplePage createViewModel(BuildContext context) => ExamplePageViewModel();

  @override
  void awake(WrapperContext wrapperContext, ExamplePageViewModel viewModel) => viewModel.setup(initValue);

  @override
  Widget build(BuildContext context, ExamplePageViewModel viewModel) {
    return BuildYourUiWidget();;
  }
}

4 - Listen to data changes from ViewModel #

Listen to data changes from ViewModel and update UI with StreamDataConsumer.

A StreamDataConsumer is a widget that listens to changes in a data stream and updates its UI accordingly. It can be used to display data from a ViewModel and update the UI whenever the data changes.

To use a StreamDataConsumer, you first need to create a data stream in your ViewModel. This can be done using a StreamDataViewModel .

Once you have created the data stream, you can pass it to a StreamDataConsumer widget as a parameter. The StreamDataConsumer will then listen to changes in the data stream and update its UI accordingly.

For example, if you have a counter variable in your ViewModel that you want to display in your UI, you can create a StreamDataViewModel for it and pass it to a StreamDataConsumer widget. Whenever the counter changes, the StreamDataConsumer will update its UI to display the new value.

Widget _buildCounterDisplay(ExamplePageViewModel viewModel) {
  return Center(
    child: StreamDataConsumer<int>(
      streamData: viewModel.uiState,
      builder: (context, data) {
        return Text("You have pressed the button $data times.");
      },
    ),
  );
}

Full Example #

class ExamplePage extends ViewModelWidget<ExamplePageViewModel> {
  const ExamplePage({Key? key}) : super(key: key);

  @override
  ExamplePageViewModel createViewModel(BuildContext context) => ExamplePageViewModel();

  @override
  Widget build(BuildContext context, ExamplePageViewModel viewModel) {
    return Scaffold(
      body: Column(
        children: [
          _buildCounterDisplay(viewModel),
          _buildButtonPlus(viewModel),
        ],
      ),
    );
  }

  Widget _buildButtonPlus(ExamplePageViewModel viewModel) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: ElevatedButton(
        onPressed: () {
          viewModel.increaseCounter();
        },
        child: const Text("+"),
      ),
    );
  }

  Expanded _buildCounterDisplay(ExamplePageViewModel viewModel) {
    return Expanded(
      child: Center(
        child: StreamDataConsumer<int>(
          streamData: viewModel.uiState,
          builder: (context, data) {
            return Text("You have pressed the button $data times.");
          },
        ),
      ),
    );
  }
}

class ExamplePageViewModel extends ViewModel {
  ExamplePageViewModel();

  late final _uiState = 0.mutableData(this);
  late final uiState = _uiState.streamData;

  void increaseCounter() {
    _uiState.postValue(_uiState.data + 1);
  }
}

API: #

ViewModelWidget

  • awake
  • createViewModel
  • build

ViewModel

  • onInitState
  • onResume
  • onPause
  • onDispose
  • onApplicationResumed
  • onApplicationInactive
  • onApplicationPaused
  • onApplicationDetached

StreamData

  • data
  • asStream

StreamDataViewModel

  • postValue
  • setValue
  • asStream
  • close

Additional Information #

Any PR is a great help. Thanks

1
likes
160
points
66
downloads

Publisher

unverified uploader

Weekly Downloads

maac_mvvm is a package supporting easy MVVM pattern implementation without any dependency injection wrapping, allowing freedom of choice.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

async, flutter, visibility_detector

More

Packages that depend on maac_mvvm