Removed Inherited Generics

This commit is contained in:
Vadim 2023-08-13 21:59:37 +02:00
parent a9102d4e7d
commit 28c72d492f
16 changed files with 156 additions and 147 deletions

View file

@ -1,12 +1,9 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/providers/services_provider.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'package:uuid/uuid.dart';
// TODO(@vodemn): This will be removed in #89
typedef EquipmentProfiles = List<EquipmentProfile>;
class EquipmentProfileProvider extends StatefulWidget {
final Widget child;
@ -51,12 +48,10 @@ class EquipmentProfileProviderState extends State<EquipmentProfileProvider> {
@override
Widget build(BuildContext context) {
return InheritedWidgetBase<List<EquipmentProfile>>(
data: [_defaultProfile] + _customProfiles,
child: InheritedWidgetBase<EquipmentProfile>(
data: _selectedProfile,
child: widget.child,
),
return EquipmentProfiles(
profiles: [_defaultProfile] + _customProfiles,
selected: _selectedProfile,
child: widget.child,
);
}
@ -101,3 +96,42 @@ class EquipmentProfileProviderState extends State<EquipmentProfileProvider> {
setState(() {});
}
}
// Copied from #89
enum EquipmentProfilesAspect { list, selected }
class EquipmentProfiles extends InheritedModel<EquipmentProfilesAspect> {
const EquipmentProfiles({
super.key,
required this.profiles,
required this.selected,
required super.child,
});
final List<EquipmentProfile> profiles;
final EquipmentProfile selected;
static List<EquipmentProfile> of(BuildContext context) {
return InheritedModel.inheritFrom<EquipmentProfiles>(
context,
aspect: EquipmentProfilesAspect.list,
)!
.profiles;
}
static EquipmentProfile selectedOf(BuildContext context) {
return InheritedModel.inheritFrom<EquipmentProfiles>(
context,
aspect: EquipmentProfilesAspect.selected,
)!
.selected;
}
@override
bool updateShouldNotify(EquipmentProfiles oldWidget) => false;
@override
bool updateShouldNotifyDependent(
EquipmentProfiles oldWidget, Set<EquipmentProfilesAspect> dependencies,) =>
false;
}

View file

@ -2,12 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/data/models/film.dart';
import 'package:lightmeter/interactors/metering_interactor.dart';
import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart';
import 'package:lightmeter/screens/metering/components/camera_container/bloc_container_camera.dart';
import 'package:lightmeter/screens/metering/components/camera_container/event_container_camera.dart';
import 'package:lightmeter/screens/metering/components/camera_container/widget_container_camera.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/metering/flow_metering.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class CameraContainerProvider extends StatelessWidget {
@ -39,7 +38,7 @@ class CameraContainerProvider extends StatelessWidget {
return BlocProvider(
lazy: false,
create: (context) => CameraContainerBloc(
context.get<MeteringInteractor>(),
MeteringInteractorProvider.of(context),
context.read<MeteringCommunicationBloc>(),
)..add(const RequestPermissionEvent()),
child: CameraContainer(

View file

@ -2,11 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/data/models/film.dart';
import 'package:lightmeter/interactors/metering_interactor.dart';
import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart';
import 'package:lightmeter/screens/metering/components/light_sensor_container/bloc_container_light_sensor.dart';
import 'package:lightmeter/screens/metering/components/light_sensor_container/widget_container_light_sensor.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/metering/flow_metering.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class LightSensorContainerProvider extends StatelessWidget {
@ -38,7 +37,7 @@ class LightSensorContainerProvider extends StatelessWidget {
return BlocProvider(
lazy: false,
create: (context) => LightSensorContainerBloc(
context.get<MeteringInteractor>(),
MeteringInteractorProvider.of(context),
context.read<MeteringCommunicationBloc>(),
),
child: LightSensorContainer(

View file

@ -9,7 +9,6 @@ import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart';
import 'package:lightmeter/screens/metering/components/shared/readings_container/components/reading_value_container/widget_container_reading_value.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class ReadingsContainer extends StatelessWidget {
@ -77,7 +76,7 @@ class ReadingsContainer extends StatelessWidget {
Expanded(
child: _IsoValuePicker(
selectedValue: iso,
values: context.listen<EquipmentProfile>().isoValues,
values: EquipmentProfiles.selectedOf(context).isoValues,
onChanged: onIsoChanged,
),
),
@ -85,7 +84,7 @@ class ReadingsContainer extends StatelessWidget {
Expanded(
child: _NdValuePicker(
selectedValue: nd,
values: context.listen<EquipmentProfile>().ndValues,
values: EquipmentProfiles.selectedOf(context).ndValues,
onChanged: onNdChanged,
),
),
@ -108,16 +107,16 @@ class _EquipmentProfilePicker extends StatelessWidget {
return AnimatedDialogPicker<EquipmentProfile>(
icon: Icons.camera,
title: S.of(context).equipmentProfile,
selectedValue: context.listen<EquipmentProfile>(),
values: context.listen<EquipmentProfiles>(),
selectedValue: EquipmentProfiles.selectedOf(context),
values: EquipmentProfiles.of(context),
itemTitleBuilder: (_, value) => Text(value.id.isEmpty ? S.of(context).none : value.name),
onChanged: EquipmentProfileProvider.of(context).setProfile,
closedChild: ReadingValueContainer.singleValue(
value: ReadingValue(
label: S.of(context).equipmentProfile,
value: context.listen<EquipmentProfile>().id.isEmpty
value: EquipmentProfiles.selectedOf(context).id.isEmpty
? S.of(context).none
: context.listen<EquipmentProfile>().name,
: EquipmentProfiles.selectedOf(context).name,
),
),
);

View file

@ -6,7 +6,6 @@ import 'package:lightmeter/screens/metering/bloc_metering.dart';
import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart';
import 'package:lightmeter/screens/metering/components/shared/volume_keys_notifier/notifier_volume_keys.dart';
import 'package:lightmeter/screens/metering/screen_metering.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class MeteringFlow extends StatefulWidget {
const MeteringFlow({super.key});
@ -18,7 +17,7 @@ class MeteringFlow extends StatefulWidget {
class _MeteringFlowState extends State<MeteringFlow> {
@override
Widget build(BuildContext context) {
return InheritedWidgetBase<MeteringInteractor>(
return MeteringInteractorProvider(
data: MeteringInteractor(
ServicesProvider.userPreferencesServiceOf(context),
ServicesProvider.caffeineServiceOf(context),
@ -27,22 +26,36 @@ class _MeteringFlowState extends State<MeteringFlow> {
ServicesProvider.lightSensorServiceOf(context),
ServicesProvider.volumeEventsServiceOf(context),
)..initialize(),
child: InheritedWidgetBase<VolumeKeysNotifier>(
data: VolumeKeysNotifier(ServicesProvider.volumeEventsServiceOf(context)),
child: MultiBlocProvider(
providers: [
BlocProvider(create: (_) => MeteringCommunicationBloc()),
BlocProvider(
create: (context) => MeteringBloc(
context.get<MeteringInteractor>(),
context.get<VolumeKeysNotifier>(),
context.read<MeteringCommunicationBloc>(),
),
child: MultiBlocProvider(
providers: [
BlocProvider(create: (_) => MeteringCommunicationBloc()),
BlocProvider(
create: (context) => MeteringBloc(
MeteringInteractorProvider.of(context),
VolumeKeysNotifier(ServicesProvider.volumeEventsServiceOf(context)),
context.read<MeteringCommunicationBloc>(),
),
],
child: const MeteringScreen(),
),
),
],
child: const MeteringScreen(),
),
);
}
}
class MeteringInteractorProvider extends InheritedWidget {
final MeteringInteractor data;
const MeteringInteractorProvider({
required this.data,
required super.child,
super.key,
});
static MeteringInteractor of(BuildContext context) {
return context.findAncestorWidgetOfExactType<MeteringInteractorProvider>()!.data;
}
@override
bool updateShouldNotify(MeteringInteractorProvider oldWidget) => false;
}

View file

@ -6,6 +6,7 @@ import 'package:lightmeter/data/models/ev_source_type.dart';
import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/data/models/film.dart';
import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/providers/equipment_profile_provider.dart';
import 'package:lightmeter/providers/services_provider.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/screens/metering/bloc_metering.dart';
@ -15,7 +16,7 @@ import 'package:lightmeter/screens/metering/components/light_sensor_container/pr
import 'package:lightmeter/screens/metering/event_metering.dart';
import 'package:lightmeter/screens/metering/state_metering.dart';
import 'package:lightmeter/screens/metering/utils/listener_metering_layout_feature.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/metering/utils/listsner_equipment_profiles.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class MeteringScreen extends StatelessWidget {
@ -72,7 +73,7 @@ class _InheritedListeners extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InheritedWidgetListener<EquipmentProfile>(
return EquipmentProfileListener(
onDidChangeDependencies: (value) {
context.read<MeteringBloc>().add(EquipmentProfileChangedEvent(value));
},
@ -146,7 +147,7 @@ class _MeteringContainerBuidler extends StatelessWidget {
final StopType stopType = UserPreferencesProvider.stopTypeOf(context);
final int evSteps = (ev * (stopType.index + 1)).round();
final EquipmentProfile equipmentProfile = context.listen<EquipmentProfile>();
final EquipmentProfile equipmentProfile = EquipmentProfiles.selectedOf(context);
final List<ApertureValue> apertureValues =
equipmentProfile.apertureValues.whereStopType(stopType);
final List<ShutterSpeedValue> shutterSpeedValues =

View file

@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/providers/equipment_profile_provider.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class EquipmentProfileListener extends StatefulWidget {
final ValueChanged<EquipmentProfile> onDidChangeDependencies;
final Widget child;
const EquipmentProfileListener({
required this.onDidChangeDependencies,
required this.child,
super.key,
});
@override
State<EquipmentProfileListener> createState() => _EquipmentProfileListenerState();
}
class _EquipmentProfileListenerState extends State<EquipmentProfileListener> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
widget.onDidChangeDependencies(EquipmentProfiles.selectedOf(context));
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}

View file

@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/interactors/settings_interactor.dart';
import 'package:lightmeter/screens/settings/components/general/components/caffeine/bloc_list_tile_caffeine.dart';
import 'package:lightmeter/screens/settings/components/general/components/caffeine/widget_list_tile_caffeine.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/settings/flow_settings.dart';
class CaffeineListTileProvider extends StatelessWidget {
const CaffeineListTileProvider({super.key});
@ -12,7 +11,7 @@ class CaffeineListTileProvider extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CaffeineListTileBloc(context.get<SettingsInteractor>()),
create: (context) => CaffeineListTileBloc(SettingsInteractorProvider.of(context)),
child: const CaffeineListTile(),
);
}

View file

@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/interactors/settings_interactor.dart';
import 'package:lightmeter/screens/settings/components/general/components/haptics/bloc_list_tile_haptics.dart';
import 'package:lightmeter/screens/settings/components/general/components/haptics/widget_list_tile_haptics.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/settings/flow_settings.dart';
class HapticsListTileProvider extends StatelessWidget {
const HapticsListTileProvider({super.key});
@ -12,7 +11,7 @@ class HapticsListTileProvider extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => HapticsListTileBloc(context.get<SettingsInteractor>()),
create: (context) => HapticsListTileBloc(SettingsInteractorProvider.of(context)),
child: const HapticsListTile(),
);
}

View file

@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/interactors/settings_interactor.dart';
import 'package:lightmeter/screens/settings/components/general/components/volume_actions/bloc_list_tile_volume_actions.dart';
import 'package:lightmeter/screens/settings/components/general/components/volume_actions/widget_list_tile_volume_actions.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/settings/flow_settings.dart';
class VolumeActionsListTileProvider extends StatelessWidget {
const VolumeActionsListTileProvider({super.key});
@ -12,7 +11,7 @@ class VolumeActionsListTileProvider extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => VolumeActionsListTileBloc(context.get<SettingsInteractor>()),
create: (context) => VolumeActionsListTileBloc(SettingsInteractorProvider.of(context)),
child: const VolumeActionsListTile(),
);
}

View file

@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/interactors/settings_interactor.dart';
import 'package:lightmeter/screens/settings/components/metering/components/calibration/components/calibration_dialog/bloc_dialog_calibration.dart';
import 'package:lightmeter/screens/settings/components/metering/components/calibration/components/calibration_dialog/widget_dialog_calibration.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/settings/flow_settings.dart';
class CalibrationDialogProvider extends StatelessWidget {
const CalibrationDialogProvider({super.key});
@ -12,7 +11,7 @@ class CalibrationDialogProvider extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CalibrationDialogBloc(context.get<SettingsInteractor>()),
create: (context) => CalibrationDialogBloc(SettingsInteractorProvider.of(context)),
child: const CalibrationDialog(),
);
}

View file

@ -1,8 +1,7 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/interactors/settings_interactor.dart';
import 'package:lightmeter/screens/settings/components/metering/components/calibration/components/calibration_dialog/provider_dialog_calibration.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:lightmeter/screens/settings/flow_settings.dart';
class CalibrationListTile extends StatelessWidget {
const CalibrationListTile({super.key});
@ -15,8 +14,8 @@ class CalibrationListTile extends StatelessWidget {
onTap: () {
showDialog<double>(
context: context,
builder: (_) => InheritedWidgetBase(
data: context.get<SettingsInteractor>(),
builder: (_) => SettingsInteractorProvider(
data: SettingsInteractorProvider.of(context),
child: const CalibrationDialogProvider(),
),
);

View file

@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/equipment_profile_provider.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/widget_container_equipment_profile.dart';
import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_name_dialog/widget_dialog_equipment_profile_name.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class EquipmentProfilesScreen extends StatefulWidget {
@ -19,13 +19,12 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
static const maxProfiles = 5 + 1; // replace with a constant from iap
late List<GlobalKey<EquipmentProfileContainerState>> profileContainersKeys = [];
int get profilesCount => context.listen<EquipmentProfiles>().length;
int get profilesCount => EquipmentProfiles.of(context).length;
@override
void initState() {
super.initState();
profileContainersKeys = context
.get<EquipmentProfiles>()
void didChangeDependencies() {
super.didChangeDependencies();
profileContainersKeys = EquipmentProfiles.of(context)
.map((e) => GlobalKey<EquipmentProfileContainerState>(debugLabel: e.id))
.toList();
}
@ -58,14 +57,14 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
),
child: EquipmentProfileContainer(
key: profileContainersKeys[index],
data: context.listen<EquipmentProfiles>()[index],
data: EquipmentProfiles.of(context)[index],
onExpand: () => _keepExpandedAt(index),
onUpdate: (profileData) => _updateProfileAt(profileData, index),
onDelete: () => _removeProfileAt(index),
),
)
: const SizedBox.shrink(),
childCount: profileContainersKeys.length,
childCount: profilesCount,
),
),
],
@ -79,7 +78,6 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
).then((value) {
if (value != null) {
EquipmentProfileProvider.of(context).addProfile(value);
profileContainersKeys.add(GlobalKey<EquipmentProfileContainerState>());
}
});
}
@ -89,8 +87,7 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
}
void _removeProfileAt(int index) {
EquipmentProfileProvider.of(context).deleteProfile(context.listen<EquipmentProfiles>()[index]);
profileContainersKeys.removeAt(index);
EquipmentProfileProvider.of(context).deleteProfile(EquipmentProfiles.of(context)[index]);
}
void _keepExpandedAt(int index) {

View file

@ -2,14 +2,13 @@ import 'package:flutter/material.dart';
import 'package:lightmeter/interactors/settings_interactor.dart';
import 'package:lightmeter/providers/services_provider.dart';
import 'package:lightmeter/screens/settings/screen_settings.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class SettingsFlow extends StatelessWidget {
const SettingsFlow({super.key});
@override
Widget build(BuildContext context) {
return InheritedWidgetBase<SettingsInteractor>(
return SettingsInteractorProvider(
data: SettingsInteractor(
ServicesProvider.userPreferencesServiceOf(context),
ServicesProvider.caffeineServiceOf(context),
@ -20,3 +19,20 @@ class SettingsFlow extends StatelessWidget {
);
}
}
class SettingsInteractorProvider extends InheritedWidget {
final SettingsInteractor data;
const SettingsInteractorProvider({
required this.data,
required super.child,
super.key,
});
static SettingsInteractor of(BuildContext context) {
return context.findAncestorWidgetOfExactType<SettingsInteractorProvider>()!.data;
}
@override
bool updateShouldNotify(SettingsInteractorProvider oldWidget) => false;
}

View file

@ -1,12 +1,11 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/interactors/settings_interactor.dart';
import 'package:lightmeter/screens/settings/components/about/widget_settings_section_about.dart';
import 'package:lightmeter/screens/settings/components/general/widget_settings_section_general.dart';
import 'package:lightmeter/screens/settings/components/metering/widget_settings_section_metering.dart';
import 'package:lightmeter/screens/settings/components/theme/widget_settings_section_theme.dart';
import 'package:lightmeter/screens/settings/flow_settings.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@ -19,12 +18,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
context.get<SettingsInteractor>().disableVolumeHandling();
SettingsInteractorProvider.of(context).disableVolumeHandling();
}
@override
void deactivate() {
context.get<SettingsInteractor>().restoreVolumeHandling();
SettingsInteractorProvider.of(context).restoreVolumeHandling();
super.deactivate();
}

View file

@ -1,73 +0,0 @@
import 'package:flutter/widgets.dart';
/// Listening to multiple dependencies at the same time causes firing an event for all dependencies
/// even though some of them didn't change:
/// ```dart
/// @override
/// void didChangeDependencies() {
/// super.didChangeDependencies();
/// _bloc.add(EquipmentProfileChangedEvent(EquipmentProfile.of(context)));
/// if (!MeteringScreenLayout.featureStatusOf(context, MeteringScreenLayoutFeature.filmPicker)) {
/// _bloc.add(const FilmChangedEvent(Film.other()));
/// }
/// }
/// ```
/// To overcome this issue I've decided to create a generic listener,
/// that will listen to each dependency separately.
class InheritedWidgetListener<T> extends StatefulWidget {
final ValueChanged<T> onDidChangeDependencies;
final Widget child;
const InheritedWidgetListener({
required this.onDidChangeDependencies,
required this.child,
super.key,
});
@override
State<InheritedWidgetListener<T>> createState() => _InheritedWidgetListenerState<T>();
}
class _InheritedWidgetListenerState<T> extends State<InheritedWidgetListener<T>> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
widget.onDidChangeDependencies(context.listen<T>());
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
class InheritedWidgetBase<T> extends InheritedWidget {
final T data;
const InheritedWidgetBase({
required this.data,
required super.child,
super.key,
});
static T of<T>(BuildContext context, {bool listen = true}) {
if (listen) {
return context.dependOnInheritedWidgetOfExactType<InheritedWidgetBase<T>>()!.data;
} else {
return context.findAncestorWidgetOfExactType<InheritedWidgetBase<T>>()!.data;
}
}
@override
bool updateShouldNotify(InheritedWidgetBase<T> oldWidget) => true;
}
extension InheritedWidgetBaseContext on BuildContext {
T get<T>() {
return InheritedWidgetBase.of<T>(this, listen: false);
}
T listen<T>() {
return InheritedWidgetBase.of<T>(this);
}
}