package GitHub repository

Flutter AppRun

A lightweight, easy-to-use, event-driven state management system, highly inspired by AppRun JS.


  • Use events to drive state changes, easy to understand.
  • Use pure functions to update the state, easy to test state changes.
  • The events also drive UI updates, no need to use setState.
  • The local events are scoped to the widget, no need to worry about the global events.
  • The global events are used to communicate between widgets, no need to use Provider or Bloc.
  • Fully support asynchronous state changes.

Getting started

Install it using pub:

flutter pub add flutter_apprun

And import the package:

import 'package:flutter_apprun/flutter_apprun.dart';


Use AppRunWidget in your widget tree.

  state: initialState,
  update: update,
  builder: (BuildContext context, state) {
    return ... // widget tree biuld from the state
  • The state is the initial state
  • The update is the collection of event handlers.
  • The builder is to display the state, which is called whenever the state changes.
  • Use to trigger global events.
  • Use AppRun.of(context).run to trigger local events.


A counter page with two buttons to increment and decrement the counter.

// Define the initial state
int initialState = 0;

// Define the event handler collection in a map
int add(int state, int delta) => state + delta;
Map update = {
  '@add': add,                      // global event
  '+1': (state) => add(state, 1),   // local event
  '-1': (state) => add(state, -1),  // local event

// Use the AppRunWidget in your widget tree
class HomePage extends StatelessWidget {
  final String title;

  const HomePage({super.key, required this.title});

  Widget build(BuildContext context) {
    return AppRunWidget(
      state: initialState,
      update: update,
      builder: (BuildContext context, state) {
        return Scaffold(
          appBar: AppBar(
            title: Text(title),
          body: Center(
            child: Column(
              children: <Widget>[
                  style: Theme.of(context).textTheme.headlineMedium,
          floatingActionButton: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
                heroTag: 'minus',
                // onPressed: () =>'@add', -1),  // global event
                onPressed: () => AppRun.of(context).run('-1'), // local event
                tooltip: 'Decrement',
                child: const Icon(Icons.remove),
                heroTag: 'plus',
                // onPressed: () =>'@add', 1), // global event
                onPressed: () => AppRun.of(context).run('+1'), // local event
                tooltip: 'Increment',
                child: const Icon(Icons.add),


MIT License

Additional information

Copyright (c) 2023, Yiyi Sun