Sharing Secrets Between Widgets: A Deep Dive into Flutter’s SharedAppData

Etornam Sunu Bright
3 min readJan 15, 2024

In the bustling world of Flutter development, where widgets form the building blocks of your app, data sharing can sometimes feel like trying to navigate a labyrinth. But fear not, for Flutter offers a hidden gem called SharedAppData that can streamline communication between your widgets. Let's delve into its secrets and understand how it can simplify your app's architecture.

Purpose: A Sharing Hand for Package Developers

Imagine you’re crafting a beautiful clock widget for other developers to use. This widget needs to know the current time zone, but should it force users to wrap it in a specific application-level provider just for that one piece of data? That’s where SharedAppData shines. It allows your widget to "whisper" the time zone requirement into the app's ear, without adding unnecessary complexity.

Advantages: Keeping it Lean and Mean

SharedAppData boasts several advantages that make it a compelling choice for specific scenarios:

  • Lightweight: Unlike state management solutions like Provider, it’s a minimal approach, ideal for sharing a handful of small, immutable data objects.
  • Lazy Initialization: Data is retrieved only when needed, optimizing performance.
  • Package-Friendly: Developers can seamlessly integrate their widgets into various app structures without introducing intrusive wrapper widgets.
  • Built-in: It’s readily available in the Flutter framework, requiring no additional packages.

Internals: Demystifying the Mechanism

Under the hood, SharedAppData leverages an InheritedModel widget, creating a data layer accessible to its descendants. Child widgets can "peek" into this layer using SharedAppData.getValue and "store secrets" with SharedAppData.setValue. The framework automatically rebuilds dependent widgets when data changes, ensuring everything stays in sync.

Enables sharing key/value data with its child and all of the child's descendants.

  • SharedAppData.getValue(context, key, initCallback) creates a dependency on the key and returns the value for the key from the shared data table. If no value exists for the key then the initCallback is used to create the initial value.
  • SharedAppData.setValue(context, key, value) changes the value of an entry in the shared data table and forces widgets that depend on that entry to be rebuilt.

Usage: Sharing in Practice

Let’s imagine your scaffold widget using SharedAppData:

  • Declare the SharedAppData Widget: Wrap your app’s root widget with SharedAppData
    return SharedAppData(
child: Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
//TODO: Add action
},
label: const Text('change foo')),
body: Text('Hello'),
));
  • Set the Secret: Inside your FloatingActionButton.extended widget, use SharedAppData.setValue to set the new value, using the key as foo.
    return SharedAppData(
child: Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
/// Set the new value of foo
SharedAppData.setValue<String, String?>(context, 'foo', 'FOO');
},
label: const Text('change foo')),
body: Text('Hello'),
));
  • Access the Secret: Inside your Text widget, use SharedAppData.getValue to retrieve the foo value, leveraging the provided key.
return SharedAppData(
child: Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
/// Set the new value of foo
SharedAppData.setValue<String, String?>(context, 'foo', 'FOO');
},
label: const Text('change foo')),
body: Text(SharedAppData.getValue(context, 'foo', () => 'initial value')),
));
  • Keep it Immutable: Remember, only immutable data should be stored in SharedAppData to avoid unnecessary rebuilds.

Remember:

  • SharedAppData is not a general-purpose state management solution. It's best suited for sharing small, specific pieces of data within a package's scope.
  • Avoid overloading it with too much data, as it can lead to performance issues.
  • Consider alternative solutions like Provider, BLoC or Riverpod for complex state management scenarios.

Conclusion:

SharedAppData is a powerful tool for package developers to share essential data with their widgets in a lightweight and efficient manner. By understanding its purpose, advantages, and internals, you can leverage its potential to create seamless and modular Flutter applications. So, the next time you need to share secrets between your widgets, remember this hidden gem in the Flutter arsenal!

I hope this article provides a comprehensive overview of SharedAppData. Feel free to ask any further questions you might have!

--

--

Etornam Sunu Bright

Mobile and Backend engineering. Flutter Africa Community Co-organizer 🌍.