Cover Image

Overview

You can quickly create Stateless and Stateful InheritedWidgets to access data at multiple locations within your widget tree. Below are Live Templates for use in Android Studio that will help you create these.

Stateless Inherited Widget

Live Template

import 'package:flutter/widgets.dart';

class $name$ extends InheritedWidget {
  final $type$ $value$;

  // of method
  static $name$ of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<$name$>()!;
  }

  const $name$({super.key, required super.child});

  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) => true;
}

Usage

class HomeView extends StatelessWidget {
  const HomeView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return HomeViewModel(
      title: 'Home',
      child: Scaffold(
        body: Builder(
          builder: (context) {
            return Center(child: Text( HomeViewModel.of(context).title));
          }
        )
      ),
    );
  }
}

Stateful Inherited Widget

Live Template

class $name$ extends StatefulWidget {
  const $name$({Key? key, required this.child}) : super(key: key);
  final Widget child;

  static $name$State of(BuildContext context) => (context.dependOnInheritedWidgetOfExactType<_$name$>() as _$name$).state;

  @override
  $name$State createState() => $name$State();
}

class $name$State extends State<$name$> {
  @override
  Widget build(BuildContext context) => _$name$(
        state: this,
        child: widget.child,
      );
}

class _$name$ extends InheritedWidget {
  const _$name$({Key? key, required Widget child, required this.state}) : super(key: key, child: child);
  final $name$State state;

  @override
  // Always rebuild children if state changes
  bool updateShouldNotify(covariant InheritedWidget oldWidget) => true;
}

Usage

class HomeView extends StatelessWidget {
  const HomeView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return HomeViewModel(
      child: Scaffold(
        body: Builder(
          builder: (context) {
            return Center(child: Text(HomeViewModel.of(context).title));
          },
        ),
      ),
    );
  }
}

To access data in both the stateful and stateless InheritedWidgets, you need to use a BuildContext that is inside the InheritedWidget. Here I’ve used the Builder widget to introduce a new context object with the appropriate access. If you do not use the correct context, you’ll receive an error when the .of(context) method is called:

type 'Null' is not a subtype of type '_HomeViewModel' in type cast

Commentary

While InheritedWidgets require a bit of boilerplate code, they can easily replace most state management solutions if used correctly. By enabling you to read and update data from anywhere in your application, these widgets can supercharge your Flutter applications without requiring a third-party dependency. In fact, one of the most attractive things about Inherited widgets is that they are built into the Flutter framework and optimized for sprawling widget trees. You don’t need to depend on Provider, Riverpod, Bloc, or any of the other state management packages that have popped up over the years. It’s pure Flutter.

The boilerplate code is a bit of a hassle but with these Live Templates, you won’t need to remember the exact syntax required to get things setup. For simple, unchanging data you need throughout your app, use the Stateless implementation. For more involved use cases, like when you want access to a chunk of business logic on a few screens, use the Stateful implementation.

Happy Coding 🍹