Removed InheritedModelAspectListener

This commit is contained in:
Vadim 2023-08-13 21:30:14 +02:00
parent c01cdc9dce
commit cc10ed26bd
3 changed files with 55 additions and 100 deletions

View file

@ -14,6 +14,7 @@ import 'package:lightmeter/screens/metering/components/camera_container/provider
import 'package:lightmeter/screens/metering/components/light_sensor_container/provider_container_light_sensor.dart';
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:m3_lightmeter_resources/m3_lightmeter_resources.dart';
@ -75,8 +76,8 @@ class _InheritedListeners extends StatelessWidget {
onDidChangeDependencies: (value) {
context.read<MeteringBloc>().add(EquipmentProfileChangedEvent(value));
},
child: InheritedModelAspectListener<MeteringScreenLayoutFeature, bool>(
aspect: MeteringScreenLayoutFeature.filmPicker,
child: MeteringScreenLayoutFeatureListener(
feature: MeteringScreenLayoutFeature.filmPicker,
onDidChangeDependencies: (value) {
if (!value) context.read<MeteringBloc>().add(const FilmChangedEvent(Film.other()));
},

View file

@ -0,0 +1,52 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/providers/user_preferences_provider.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 MeteringScreenLayoutFeatureListener extends StatefulWidget {
final MeteringScreenLayoutFeature feature;
final ValueChanged<bool> onDidChangeDependencies;
final Widget child;
const MeteringScreenLayoutFeatureListener({
required this.feature,
required this.onDidChangeDependencies,
required this.child,
super.key,
});
@override
State<MeteringScreenLayoutFeatureListener> createState() =>
_MeteringScreenLayoutFeatureListenerState();
}
class _MeteringScreenLayoutFeatureListenerState extends State<MeteringScreenLayoutFeatureListener> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
widget.onDidChangeDependencies(
UserPreferencesProvider.meteringScreenFeatureOf(
context,
widget.feature,
),
);
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}

View file

@ -71,101 +71,3 @@ extension InheritedWidgetBaseContext on BuildContext {
return InheritedWidgetBase.of<T>(this);
}
}
/// 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 InheritedModelAspectListener<A extends Object, T> extends StatefulWidget {
final A aspect;
final ValueChanged<T> onDidChangeDependencies;
final Widget child;
const InheritedModelAspectListener({
required this.aspect,
required this.onDidChangeDependencies,
required this.child,
super.key,
});
@override
State<InheritedModelAspectListener<A, T>> createState() =>
_InheritedModelAspectListenerState<A, T>();
}
class _InheritedModelAspectListenerState<A extends Object, T>
extends State<InheritedModelAspectListener<A, T>> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
widget.onDidChangeDependencies(context.listenModelFeature<A, T>(widget.aspect));
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
class InheritedModelBase<A, T> extends InheritedModel<A> {
final Map<A, T> data;
const InheritedModelBase({
required this.data,
required super.child,
super.key,
});
static Map<A, T> of<A, T>(BuildContext context, {bool listen = true}) {
if (listen) {
return context.dependOnInheritedWidgetOfExactType<InheritedModelBase<A, T>>()!.data;
} else {
return context.findAncestorWidgetOfExactType<InheritedModelBase<A, T>>()!.data;
}
}
static T featureOf<A extends Object, T>(BuildContext context, A aspect) {
return InheritedModel.inheritFrom<InheritedModelBase<A, T>>(context, aspect: aspect)!
.data[aspect]!;
}
@override
bool updateShouldNotify(InheritedModelBase oldWidget) => true;
@override
bool updateShouldNotifyDependent(
InheritedModelBase<A, T> oldWidget,
Set<A> dependencies,
) {
for (final dependecy in dependencies) {
if (oldWidget.data[dependecy] != data[dependecy]) {
return true;
}
}
return false;
}
}
extension InheritedModelBaseContext on BuildContext {
Map<A, T> getModel<A, T>() {
return InheritedModelBase.of<A, T>(this, listen: false);
}
Map<A, T> listenModel<A, T>() {
return InheritedModelBase.of<A, T>(this);
}
T listenModelFeature<A extends Object, T>(A aspect) {
return InheritedModelBase.featureOf<A, T>(this, aspect);
}
}