Repository: flutter
Issue: Add a variant to context.dependOnInheritedWidget that removes the unused dependencies when the dependent no-longer depends on it
Labels: c: new feature,framework,c: proposal,P3,team-framework,triaged-framework

This is related to https://github.com/flutter/flutter/issues/12992#issuecomment-1165029133

## Use-case

Currently, widgets never stop listening to an InheritedWidget, even if they stop using it. As such, the code:

```dart
Widget build(context) {
  if (condition) {
    context.dependOnInheritedWidgetOfExactType<T>();
  }
}
```

when `condition` changes from true to false, the consumer will keep rebuilding when the InheritedWidget changes.


That current behavior is supposedly a performance optimization. To quote Hixie:

> This was an intentional performance optimization - by not having to clear the dependencies each frame, we can avoid a lot of work.

The problem is, while for simple usages that's fine, this behavior is incompatible with some use-cases

For example, in package:riverpod, one core feature is [autoDispose], which is incompatible with this behavior.
In Riverpod, [autoDispose](https://riverpod.dev/docs/concepts/modifiers/auto_dispose) is used to free the resources linked to an InheritedWidget when that InheritedWidget stops being used.


The problem with this behavior is:
If a consumer widget stops calling to `context.dependOnInheritedWidget `, users would expect [autoDispose] to take effect and free the resources.  
But that wouldn't be the case as the consumer widget will not unsubscribe to the InheritedWidget until its element is unmounted. This would delay the effect of [autoDispose] by potentially a significant amount of time, or simply prevent it to take effect.


___

Currently, package:riverpod works around that issue by not relying on `context.dependOnInheritedWidget`.

This leads to an ugly workaround, which is subclassing StatelessWidget/StatefulWidget to override Element.build (cf [ConsumerWidget](https://pub.dev/documentation/flutter_riverpod/latest/flutter_riverpod/ConsumerWidget-class.html), a custom StatelessWidget-like)

While this workaround works, it has an important downside:
This leads to package:riverpod being used differently from what Flutter typically does.
Instead of a:

```dart
class Example extends StatelessWidget {
  Widget build(BuildContext context) {
    MyInheritedWidget.of(context);
  }
}
```
Riverpod users have to do:
```dart
class Example extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) {
    MyInheritedWidget.of(ref);
  }
}
```

This difference is the reason why I had to basically stop developing package:provider and instead start working on package:riverpod, as package:provider couldn't keep using the `context` syntax while supporting [autoDispose] which is a core feature for numerous commonly requested enhancements.



Implementing this feature along with https://github.com/flutter/flutter/issues/106546 would allow package:riverpod to use the `context` API again. This would both significantly simplify its usage and allow fusing package:riverpod/package:provider


## Proposal

Since the described behavior exists as a performance optimization, my proposal would be to keep the default behavior of `context.dependOnInheritedWidget` as is, and instead add a new API

This could either be a flag

```dart
context.dependOnInheritedWidgetOfExactType<T>(removeDependencyOnRebuild: true);
```

or a new BuildContext method (although I'm not sure how to name it).


This flag/method would tell `ComponentElement` to keep track of the InheritedWidget dependencies within `ComponentElement.build`, and remove the unused ones.


This feature would need to consider  https://github.com/flutter/flutter/issues/106546, to avoid calling InheritedWidget.removeDependent every time the consumer rebuilds, and instead only when a consumer truly stops listening to an InheritedWidget.

[family]: https://riverpod.dev/docs/concepts/modifiers/family/
[autoDispose]: https://riverpod.dev/docs/concepts/modifiers/auto_dispose