mvvm_service 1.1.2 copy "mvvm_service: ^1.1.2" to clipboard
mvvm_service: ^1.1.2 copied to clipboard

A Flutter-native service layer inspired by the MVVM pattern, managing services according to the widget lifecycle, without relying on Provider or Riverpod.

example/main.dart

import 'package:flutter/material.dart';
import 'package:mvvm_service/mvvm_service.dart';

/// A simple example service that extends [Service] with integer data.
/// It increments a static counter each time [fetchData] is called.
class ExampleService extends Service<int> {
  static int count = 0;

  // Simulates fetching data asynchronously with a 1-second delay.
  @override
  Future<int> fetchData() async {
    await Future.delayed(Duration(seconds: 1));
    return count += 1;
  }
}

void main() {
  runApp(const MainApp());
}

/// The main application widget.
class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(child: Center(child: ExampleWidget())),
      ),
    );
  }
}

/// A widget that uses [ExampleService] via [ServiceWidget].
/// Displays a loading indicator while data is being fetched,
/// and the fetched integer once available.
class ExampleWidget extends ServiceWidget<ExampleService> {
  const ExampleWidget({super.key});

  /// Provides the initial instance of [ExampleService].
  @override
  ExampleService get initialService => ExampleService();

  /// Builds the UI based on the current state of the service.
  /// Shows a [CircularProgressIndicator] while loading,
  /// and displays the service's integer data once loaded.
  @override
  Widget build(BuildContext context, ExampleService service) {
    // Alternatively, you can use the `when` extension on the service
    // to declaratively build widgets based on its current state.
    // This keeps the UI code concise and clearly maps each state
    // (loading, failed, loaded, refresh) to a corresponding widget.
    //
    // Example:
    //
    // service.when(
    //   none: () => Text("Service is none"),
    //   loading: () => CircularProgressIndicator(), // Shown while data is loading
    //   refresh: () => CircularProgressIndicator(), // Optional: Shown during a refresh
    //   failed: (error) => Text("Service failed: $error"), // Shown if an error occurs
    //   loaded: (data) => Text("Data: $data"), // Shown when data is successfully loaded
    // );

    if (service.isLoading) {
      return CircularProgressIndicator();
    }

    if (service.isError) {
      return Text("Service is failed: ${service.error}");
    }

    return ExampleSubtreeWidget();
  }
}

/// A subtree widget that depends on [ExampleService] using [ServiceWidgetOf].
/// Displays the loaded integer data with a refresh mechanism.
class ExampleSubtreeWidget extends ServiceWidgetOf<ExampleService> {
  const ExampleSubtreeWidget({super.key});

  @override
  Widget build(BuildContext context, ExampleService service) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 15,
      children: [
        Opacity(
          opacity: service.isRefreshing ? 0.5 : 1,
          child: Text(service.data.toString()),
        ),
        // Simple refresh implementation.
        IgnorePointer(
          ignoring: service.isRefreshing,
          child: TextButton(onPressed: service.refresh, child: Text("Refesh")),
        ),
      ],
    );
  }
}
0
likes
160
points
53
downloads

Publisher

verified publisherttangkong.dev

Weekly Downloads

A Flutter-native service layer inspired by the MVVM pattern, managing services according to the widget lifecycle, without relying on Provider or Riverpod.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on mvvm_service