搜索插件、代码仓与 APP 分类

插件详情v0.6.0

reduced

状态管理框架基本功能的统一外观。

AndroidiOSWebmacOSWindowsLinux
近 30 天下载
18
喜欢数
39
Pub 分数
145

安装插件

flutter pub add reduced

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

Reduced 为流行的 Flutter 状态管理框架中的核心状态管理功能提供了一个统一的外观。它通过提供一致的 API 来简化集成,无论底层框架如何,都能轻松管理状态、处理依赖关系并响应变化。专为希望在不产生样板代码的情况下获得灵活性的开发者设计,Reduced 抽象了复杂性,同时保持了性能和可扩展性。非常适合可能在多种状态管理解决方案之间切换或组合使用的项目。

适合场景

  • 简化跨多个框架的状态管理
  • 创建可移植的状态逻辑
  • 减少有状态小部件中的样板代码
  • 启用框架无关的状态处理
  • 支持混合状态管理方法

主要特点

  • 统一的状态管理 API
  • 框架无关设计
  • 最小化样板代码
  • 内置依赖注入支持
  • 与现有状态解决方案的无缝集成

适合对象

  • 使用多个状态管理库的开发者
  • 需要灵活状态架构的项目
  • 致力于降低复杂性的团队
  • 需要未来可扩展状态设计的应用程序
  • 使用可互换状态模式进行原型设计

使用建议

  • 由于抽象层可能导致轻微开销
  • 最适合中大型应用程序
  • 需要理解底层状态概念
  • 仅限支持的状态管理后端
  • 不建议用于简单的单次应用程序

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

GitHub release (latest by date) GitHub Workflow Status GitHub code size in bytes GitHub last commit GitHub commit activity

reduced

Unified facade for the basic features of state management frameworks:

  1. Read a current state value.
  2. Update a current state value.
  3. Callbacks with value semantics

The app logic based mainly on these features should remain as independent as possible from the state management framework used. Therefore, the app logic needs a neutral state management API and an implementation of this API for the state management framework used.
The former is provided by this package. The latter is provided by other packages listed at the end of the README.

Features

The 'reduced' facade covers the following features of a state management framework:

1. Read a current state value.
abstract class Store {
    S get state;
    ...
}

Samples of Store.get state use

get state => super.state;
reduced_riverpod/lib/src/riverpod_store.dart#L11

get state => _state;
reduced_getx/lib/src/getx_store.dart#L14

2. Update a current state value.
abstract class Store {
    ...
  void process(Event<S> event);
}

Instead of writing the state value directly, the facade provides a process method that accepts a called event as a parameter. In the process method the event is executed with the current state value as a parameter and the return value of the event is stored as the new state value.

Samples of Store.process use

process(event) => add(event);
reduced_bloc/lib/src/bloc_store.dart#L15

process(event) => state = event(state);
reduced_riverpod/lib/src/riverpod_store.dart#L14

abstract class Event<S> {
    S call(S state);
}

All Event implementations must be derived from the Event base class.

Samples of Event use

class CounterIncremented extends Event<int>
reduced/example/counter_app/lib/logic.dart#L7

2.1 SnapshotToPropsMapper function typedef
typedef SnapshotToPropsMapper<S, P> = P Function(
  StoreSnapshot<S> snapshot,
  String? routeName,
);

A SnapshotToPropsMapper is a Function that uses the snapshot and the routeName parameters to map the current state of a store into a derived 'selective' state value. Only the changes to this derived 'selective' state value determine whether a rebuild of the widget is triggered. In order for changes to be detected correctly, the derived 'selective' state value must have value semantics.
With a SnapshotToPropsMapper function usually a props parameter for a WidgetFromPropsBuilder function is created.

Samples of SnapshotToPropsMapper use

required SnapshotToPropsMapper<S, P> mapper,
reduced_bloc/lib/src/bloc_widgets.dart#L33

2.2 WidgetFromPropsBuilder function typedef
typedef WidgetFromPropsBuilder<P> = Widget Function({
  Key? key,
  required P props,
});

A WidgetFromPropsBuilder is a Function that builds a new widget from the properties of the passed props parameter. That is, the props parameter must contain all the properties necessary for building the widget.

Samples of WidgetFromPropsBuilder use

final WidgetFromPropsBuilder<MyHomePageProps> builder;
reduced/example/counter_app_with_selective_rebuild/lib/consumer.dart#L16

required WidgetFromPropsBuilder<P> builder,
reduced_bloc/lib/src/bloc_widgets.dart#L34

2.3 Events with additional parameters
abstract class Event1<S, V> {
  S call(S state, V value);
}
abstract class Event2<S, V1, V2> {
  S call(S state, V1 value1, V2 value2);
}
abstract class Event3<S, V1, V2, V3> ...

Sample of Event1 use

class ItemAdded extends Event1<AppState, int>
reduced/example/shopper_app/lib/models/events.dart#L9

2.4 Adapter implementations for Events with parameters
class Parametrized1Event<S, V> extends Event<S> {
  Parametrized1Event(this.adaptee, this.value);

  final Event1<S, V> adaptee;
  final V value;

  @override call(state) => adaptee.call(state, value);

  @override get hashCode => ...
  @override operator ==(other) ...
}
class Parametrized2Event<S, V1, V2> extends Event<S> ...
class Parametrized3Event<S, V1, V2, V3> extends Event<S> ...

Sample of Parametrized1Event use

Parametrized1Event(ItemRemoved(), value),
reduced/example/shopper_app/lib/models/event.dart#L37

3. Callbacks with value semantics

Many widgets have callback properties of type Function. The Function type has no value semantics (each function is unique), this also applies to anonymous functions, which are often used as values ​​for widget callback properties. If value semantics are needed, Callable can be used for callback properties in the derived 'selective' state values instead of anonymous functions.

abstract class Callable<T> {
    T call();
}
abstract class Callable1<T, V> {
    T call(V value);
}
abstract class Callable2<T, V1, V2> {
    T call(V1 value1, V2 value2);
}
abstract class Callable3<T, V1, V2, V3> {
    T call(V1 value1, V2 value2, V3 value3);
}

Samples of Callable use

typedef VoidCallable = Callable<void>;
reduced/lib/src/callbacks.dart#L395

final Callable<void> onPressed;
reduced/example/counter_app/lib/logic.dart#L15

If the signatures of a widget callback property's function and the call method of a callable match, then the callable is assignment-compatible with the widget callback property, e.g.:

Callable1<String?, String> validator = ...
TextFormField(
    validator: validator,
    ...
);
3.1 Command - Adapter implementations of Callable(s)

An Command carries an event to an EventProcessor and let the processor process the event.

class Command<S> extends Callable<void> {
  const Command(this.processor, this.event);

  final EventProcessor<S> processor;
  final Event<S> event;

  @override call() => processor.process(event);
  @override get hashCode => ...
  @override operator ==(other) => ...
}
class Command1<S, V> extends Callable1<void, V> ...
class Command2<S, V1, V2> extends Callable2<void, V1, V2> ...
class Command3<S, V1, V2, V3> 
  extends Callable3<void, V1, V2, V3> ...

Samples of Command use

onPressed: Command(snapshot.processor, CounterIncremented()), reduced/example/counter_app/lib/logic.dart#L23

Getting started

In the pubspec.yaml add dependencies on the package 'reduced' and on the package of an implementation of the 'reduced' facade for a state management framework, e.g. 'reduced_bloc'.

dependencies:
  reduced: 0.6.0
  reduced_bloc: 
    git: 
      url: https://github.com/partmaster/reduced_bloc.git
      ref: v0.6.0

Import package 'reduced' to implement the logic.

import 'package:reduced/reduced.dart';

Import choosen implementation package for the 'reduced' facade to use the logic, e.g.

import 'package:reduced_bloc/reduced_bloc.dart';

Usage (Part 1)

Implementation of the counter demo app logic with the 'reduced' facade without further dependencies on state management packages.

// logic.dart

import 'package:flutter/material.dart' hide Action;
import 'package:reduced/callbacks.dart';
import 'package:reduced/reduced.dart';

class CounterIncremented extends Event<int> {
  @override
  int call(int state) => state + 1;
}

class Props {
  const Props({required this.counterText, required this.onPressed});

  final String counterText;
  final VoidCallable onPressed;
}

class PropsMapper extends Props {
  PropsMapper(StoreSnapshot<int> snapshot, String? routeName)
      : super(
          counterText: '${snapshot.state}',
          onPressed: Command(
            snapshot.processor,
            CounterIncremented(),
          ),
        );
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.props});

  final Props props;

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('reduced_bloc example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text(
                'You have pushed the button this many times:',
              ),
              Text(props.counterText),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: props.onPressed,
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
      );
}

Extended Features

In addition to the basic features, state management frameworks also offer these advanced features:

  1. Register a state for management.
  2. Trigger a rebuild on widgets selectively after a state change.
  3. Set up a new scope for state management.

A neutral facade has also been developed for this features in the form of the registerState function and the ReducedProvider, ReducedConsumer and ReducedScope widget classes. Since the features differ for the concrete frameworks, the signatures of the function and the widget constructors are also different, so these function and classes were not included in the 'reduced' facade, but are part of the additional API of the implementations of the 'reduced' facade.

1. Register a state for management.
void registerState(S initialValue);
class ReducedProvider<S> extends Statelesswidget {
  ReducedProvider({
    required this.initialState,
    required this.child,
  }) ...

  final S initialState, 
  final Widget child,
  ...
}
2. Trigger a rebuild on widgets selectively after a state change.
class ReducedConsumer<S, P> extends StatelessWidget {
  const ReducedConsumer({
    super.key,
    required this.mapper,
    required this.builder,
  }) ...

  final SnapshotToPropsMapper<S, P> mapper;
  final WidgetFromPropsBuilder<P> builder;
  ...
}
3. Set up a new scope for state management.
class ReducedScope extends StatelessWidget {
  ReducedScope({
    required this.child,
  }) ...
  
  final Widget child,
  ...
}

Usage (Part 2)

Finished counter demo app using logic.dart and 'reduced_bloc' package, an implementation of the 'reduced' API on Bloc:

// main.dart

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

import 'logic.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) => ReducedProvider(
        initialState: 0,
        child: MaterialApp(
          theme: ThemeData(primarySwatch: Colors.blue),
          home: Builder(
            builder: (context) => const ReducedConsumer(
              mapper: PropsMapper.new,
              builder: MyHomePage.new,
            ),
          ),
        ),
      );
}

Additional information

Implementations of the 'reduced' API are available for the following state management frameworks:

framework implementation package for 'reduced' API
Binder reduced_binder
Bloc reduced_bloc
FlutterCommand reduced_fluttercommand
FlutterTriple reduced_fluttertriple
GetIt reduced_getit
GetX reduced_getx
MobX reduced_mobx
Provider reduced_provider
Redux reduced_redux
Riverpod reduced_riverpod
Solidart reduced_solidart
StatesRebuilder reduced_statesrebuilder

所属分类

依赖

依赖清单 1 项

源码仓库

使用此插件的项目

暂无相关数据。