Edit: solved by adding a unique key
to the widget constructor
call:
Edit 2: as Randal Schwartz mentioned -> this is not a solution. Issue NOT solved and still open.
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
key: UniqueKey(),
currentSearchTermInputContent:
widgetRef.read(apiEndpointUniversalSearchTermInputContentProvider),
captionList: ["Statement"],
// todo : allow umlauts! or better deny numbers?
inputFormatterAllow: RegExp(".*"),
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
I have an abstract class
(ApiEndpoint) with two implementation
s (ApiEndpointName, ApiEndpointUniversal).
Both implementation
s have a StatefulWidget
(SearchTermInputOneString) inherit
ed from the same base class
(SearchTermInput).
For both ApiEndpoint-objects the Widget part of SearchTermInputOneStringis created separately - what is correct. My problem is, that the State-part of SearchTermInputOneString is created only once - so ApiEndpointName and ApiEndpointUniversal own the same state.
I have to read ApiEndpoint-specific configuration during initState
- that does not work because initState
is called only for the first ApiEndpoint-instance :(
Any ideas how to solve that?
abstract class
ApiEndpoint:
enum ApiEndpointType {
today,
unseen,
universal,
name,
exactAge,
ageBetween,
ageGreaterThanOrEqual,
ageLessThanOrEqual
}
abstract class ApiEndpoint {
ApiEndpointType get type;
String get title;
SearchTermInput get searchTermInput;
String get searchFunctionName;
bool validateData(BuildContext context, WidgetRef ref);
void onSubmit(
BuildContext context, WidgetRef ref, List<String> searchTermInputContent);
void onLostFocus(
BuildContext context, WidgetRef ref, List<String> searchTermInputContent);
}
ApiEndpointName implementation:
class ApiEndpointName implements ApiEndpoint {
final WidgetRef widgetRef;
ApiEndpointName({required this.widgetRef});
@override
String get searchFunctionName => "getObituariesByName";
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
currentSearchTermInputContent:
widgetRef.read(apiEndpointNameSearchTermInputContentProvider),
captionList: ["Name"],
inputFormatterAllow: RegExp("[a-zA-Z% ]"),
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
@override
String get title => "... by name";
@override
ApiEndpointType get type => ApiEndpointType.name;
@override
bool validateData(BuildContext context, WidgetRef ref) {
...
}
@override
void onSubmit(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
@override
void onLostFocus(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
ApiEndpointUniversal implementation:
class ApiEndpointUniversal implements ApiEndpoint {
final WidgetRef widgetRef;
ApiEndpointUniversal({required this.widgetRef});
@override
String get searchFunctionName => "getObituariesUniversal";
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
currentSearchTermInputContent:
widgetRef.read(apiEndpointUniversalSearchTermInputContentProvider),
captionList: ["Statement"],
inputFormatterAllow: RegExp(".*"),
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
@override
String get title => "... universal";
@override
ApiEndpointType get type => ApiEndpointType.universal;
@override
bool validateData(BuildContext context, WidgetRef ref) {
...
}
@override
void onSubmit(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
@override
void onLostFocus(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
}
abstract
StatefulWidget:
abstract class SearchTermInput extends ConsumerStatefulWidget {
const SearchTermInput({super.key});
List<String> get currentSearchTermInputContent;
List<String>? get captionList;
RegExp get inputFormatterAllow;
void Function(BuildContext, WidgetRef, List<String>) get onSubmit;
void Function(BuildContext, WidgetRef, List<String>) get onLostFocus;
}
Implementation:
class SearchTermInputOneString extends SearchTermInput {
@override
final List<String> currentSearchTermInputContent;
@override
final List<String> captionList;
@override
final RegExp inputFormatterAllow;
@override
final void Function(BuildContext, WidgetRef, List<String>) onSubmit;
@override
final void Function(BuildContext, WidgetRef, List<String>) onLostFocus;
const SearchTermInputOneString({
super.key,
required this.currentSearchTermInputContent,
required this.captionList,
required this.inputFormatterAllow,
required this.onSubmit,
required this.onLostFocus,
});
@override
ConsumerState<ConsumerStatefulWidget> createState() =>
_SearchTermInputOneStringState();
}
class _SearchTermInputOneStringState
extends ConsumerState<SearchTermInputOneString> {
late TextEditingController textEditingController;
@override
void initState() {
super.initState();
textEditingController = TextEditingController();
textEditingController.text = widget.currentSearchTermInputContent.isNotEmpty
? widget.currentSearchTermInputContent[0]
: "";
}
@override
void dispose() {
textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Focus(
child: TextFormField(
controller: textEditingController,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: widget.captionList.isNotEmpty ? widget.captionList[0] : "",
suffixIcon: IconButton(
onPressed: () {
textEditingController.text = "";
},
icon: Icon(Icons.clear),
),
),
inputFormatters: [
FilteringTextInputFormatter.allow(widget.inputFormatterAllow)
],
onFieldSubmitted: (_) {
widget.onSubmit(context, ref, [textEditingController.text]);
},
),
onFocusChange: (hasFocus) {
if (!hasFocus) {
widget.onLostFocus(context, ref, [textEditingController.text]);
}
},
);
}
}
I create the List of ApiEndpoints this way:
List<ApiEndpoint> getApiEndPoints({required WidgetRef widgetRef}) {
final List<ApiEndpoint> apiEndpoints = [
ApiEndpointName(widgetRef: widgetRef),
ApiEndpointUniversal(widgetRef: widgetRef),
];
return apiEndpoints;
}
Edit: solved by adding a unique key
to the widget constructor
call:
Edit 2: as Randal Schwartz mentioned -> this is not a solution. Issue NOT solved and still open.
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
key: UniqueKey(),
currentSearchTermInputContent:
widgetRef.read(apiEndpointUniversalSearchTermInputContentProvider),
captionList: ["Statement"],
// todo : allow umlauts! or better deny numbers?
inputFormatterAllow: RegExp(".*"),
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
I have an abstract class
(ApiEndpoint) with two implementation
s (ApiEndpointName, ApiEndpointUniversal).
Both implementation
s have a StatefulWidget
(SearchTermInputOneString) inherit
ed from the same base class
(SearchTermInput).
For both ApiEndpoint-objects the Widget part of SearchTermInputOneStringis created separately - what is correct. My problem is, that the State-part of SearchTermInputOneString is created only once - so ApiEndpointName and ApiEndpointUniversal own the same state.
I have to read ApiEndpoint-specific configuration during initState
- that does not work because initState
is called only for the first ApiEndpoint-instance :(
Any ideas how to solve that?
abstract class
ApiEndpoint:
enum ApiEndpointType {
today,
unseen,
universal,
name,
exactAge,
ageBetween,
ageGreaterThanOrEqual,
ageLessThanOrEqual
}
abstract class ApiEndpoint {
ApiEndpointType get type;
String get title;
SearchTermInput get searchTermInput;
String get searchFunctionName;
bool validateData(BuildContext context, WidgetRef ref);
void onSubmit(
BuildContext context, WidgetRef ref, List<String> searchTermInputContent);
void onLostFocus(
BuildContext context, WidgetRef ref, List<String> searchTermInputContent);
}
ApiEndpointName implementation:
class ApiEndpointName implements ApiEndpoint {
final WidgetRef widgetRef;
ApiEndpointName({required this.widgetRef});
@override
String get searchFunctionName => "getObituariesByName";
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
currentSearchTermInputContent:
widgetRef.read(apiEndpointNameSearchTermInputContentProvider),
captionList: ["Name"],
inputFormatterAllow: RegExp("[a-zA-Z% ]"),
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
@override
String get title => "... by name";
@override
ApiEndpointType get type => ApiEndpointType.name;
@override
bool validateData(BuildContext context, WidgetRef ref) {
...
}
@override
void onSubmit(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
@override
void onLostFocus(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
ApiEndpointUniversal implementation:
class ApiEndpointUniversal implements ApiEndpoint {
final WidgetRef widgetRef;
ApiEndpointUniversal({required this.widgetRef});
@override
String get searchFunctionName => "getObituariesUniversal";
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
currentSearchTermInputContent:
widgetRef.read(apiEndpointUniversalSearchTermInputContentProvider),
captionList: ["Statement"],
inputFormatterAllow: RegExp(".*"),
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
@override
String get title => "... universal";
@override
ApiEndpointType get type => ApiEndpointType.universal;
@override
bool validateData(BuildContext context, WidgetRef ref) {
...
}
@override
void onSubmit(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
@override
void onLostFocus(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
...
}
}
abstract
StatefulWidget:
abstract class SearchTermInput extends ConsumerStatefulWidget {
const SearchTermInput({super.key});
List<String> get currentSearchTermInputContent;
List<String>? get captionList;
RegExp get inputFormatterAllow;
void Function(BuildContext, WidgetRef, List<String>) get onSubmit;
void Function(BuildContext, WidgetRef, List<String>) get onLostFocus;
}
Implementation:
class SearchTermInputOneString extends SearchTermInput {
@override
final List<String> currentSearchTermInputContent;
@override
final List<String> captionList;
@override
final RegExp inputFormatterAllow;
@override
final void Function(BuildContext, WidgetRef, List<String>) onSubmit;
@override
final void Function(BuildContext, WidgetRef, List<String>) onLostFocus;
const SearchTermInputOneString({
super.key,
required this.currentSearchTermInputContent,
required this.captionList,
required this.inputFormatterAllow,
required this.onSubmit,
required this.onLostFocus,
});
@override
ConsumerState<ConsumerStatefulWidget> createState() =>
_SearchTermInputOneStringState();
}
class _SearchTermInputOneStringState
extends ConsumerState<SearchTermInputOneString> {
late TextEditingController textEditingController;
@override
void initState() {
super.initState();
textEditingController = TextEditingController();
textEditingController.text = widget.currentSearchTermInputContent.isNotEmpty
? widget.currentSearchTermInputContent[0]
: "";
}
@override
void dispose() {
textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Focus(
child: TextFormField(
controller: textEditingController,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: widget.captionList.isNotEmpty ? widget.captionList[0] : "",
suffixIcon: IconButton(
onPressed: () {
textEditingController.text = "";
},
icon: Icon(Icons.clear),
),
),
inputFormatters: [
FilteringTextInputFormatter.allow(widget.inputFormatterAllow)
],
onFieldSubmitted: (_) {
widget.onSubmit(context, ref, [textEditingController.text]);
},
),
onFocusChange: (hasFocus) {
if (!hasFocus) {
widget.onLostFocus(context, ref, [textEditingController.text]);
}
},
);
}
}
I create the List of ApiEndpoints this way:
List<ApiEndpoint> getApiEndPoints({required WidgetRef widgetRef}) {
final List<ApiEndpoint> apiEndpoints = [
ApiEndpointName(widgetRef: widgetRef),
ApiEndpointUniversal(widgetRef: widgetRef),
];
return apiEndpoints;
}
After playing around a lot of time without getting didChangeDependencies
to work I found out that didUpdateWidget
did the trick. Do you think that this okay or is there another stumbling block that I overlooked?
@override
void didUpdateWidget(covariant SearchTermInputOneString oldWidget) {
final log = getLogger();
log.t("didUpdateWidget");
// read apiEndpoint content
currentContent = ref
.read(widget.apiEndpointSearchTermInputContentProvider)
.cast<String>();
textEditingController.text =
currentContent.isNotEmpty ? currentContent[0] : "";
super.didUpdateWidget(oldWidget);
}
Okay, I changed my code but unfortunately I now got the same problem - the state is not updated for the second Widget-Instance (only if the first instance is disposed before!) :(
This is how the code now looks:
Widget that changes the widgets (for "Search via Name" and "Universal Search"):
@override
Widget build(BuildContext context) {
_runsAfterBuild(context, ref);
final currentApiEndpoint = ref.watch(currentApiEndpointProvider);
return Scaffold(
appBar: AppBar(
title: const Text("Search obituaries ..."),
centerTitle: true,
actions: [
IconButton(
tooltip: "Start search...",
onPressed: () {
doSearch(context, ref);
},
icon: const Icon(Icons.search)),
],
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
DropdownButtonFormField<ApiEndpoint>(
items: dropDownMenuItems,
value: currentApiEndpoint,
onChanged: (apiEndpoint) {
doOnDropDownChanged(context, ref, apiEndpoint);
}),
const SizedBox(
height: 10,
),
currentApiEndpoint.searchTermInput,
],
),
),
),
);
}
BaseClass for the ApiEndpoint implementations:
abstract class ApiEndpoint {
ApiEndpointType get type;
String get title;
SearchTermInput get searchTermInput;
String get searchFunctionName;
bool validateData(BuildContext context, WidgetRef ref);
void onSubmit(
BuildContext context, WidgetRef ref, List<String> searchTermInputContent);
void onLostFocus(
BuildContext context, WidgetRef ref, List<String> searchTermInputContent);
}
ApiEndpoint-Class that owns the widget for the first instance of the widget (Search via name):
class ApiEndpointName implements ApiEndpoint {
final log = getLogger();
final NotifierProvider<ApiEndpointNameSearchTermInputContent, List<String>>
apiEndpointSearchTermInputContentProvider =
apiEndpointNameSearchTermInputContentProvider;
ApiEndpointName();
@override
String get searchFunctionName => "getObituariesByName";
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
// key: Key("ApiEndpointName"), // UniqueKey(),
apiEndpointSearchTermInputContentProvider:
apiEndpointSearchTermInputContentProvider,
captionList: ["Name"],
textInputFormatter: [
FilteringTextInputFormatter.deny(RegExp(r"[0-9]"))
],
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
@override
String get title => "... by name";
@override
ApiEndpointType get type => ApiEndpointType.name;
@override
bool validateData(BuildContext context, WidgetRef ref) {
var contentList = ref.read(apiEndpointSearchTermInputContentProvider);
return contentList.isNotEmpty && contentList[0].isNotEmpty;
}
@override
void onSubmit(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
// set values
ref
.read(currentSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
ref
.read(apiEndpointSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
// start search
var doSearch = ref.read(doSearchFunctionProvider);
if (doSearch != null) {
doSearch(context, ref);
} else {
log.d("no doSearch method found!");
}
}
@override
void onLostFocus(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
// set values
ref
.read(currentSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
ref
.read(apiEndpointSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
}
}
ApiEndpoint-Class that owns the widget for the second instance of the widget (Universal search):
class ApiEndpointUniversal implements ApiEndpoint {
final log = getLogger();
final NotifierProvider<ApiEndpointUniversalSearchTermInputContent,
List<String>> apiEndpointSearchTermInputContentProvider =
apiEndpointUniversalSearchTermInputContentProvider;
ApiEndpointUniversal();
@override
String get searchFunctionName => "getObituariesUniversal";
@override
SearchTermInput get searchTermInput => SearchTermInputOneString(
// key: Key("ApiEndpointUniversal"), // UniqueKey(),
apiEndpointSearchTermInputContentProvider:
apiEndpointSearchTermInputContentProvider,
captionList: ["Statement"],
textInputFormatter: [FilteringTextInputFormatter.allow(RegExp(r".*"))],
onSubmit: onSubmit,
onLostFocus: onLostFocus,
);
@override
String get title => "... universal";
@override
ApiEndpointType get type => ApiEndpointType.universal;
@override
bool validateData(BuildContext context, WidgetRef ref) {
var contentList = ref.read(apiEndpointSearchTermInputContentProvider);
return contentList.isNotEmpty && contentList[0].isNotEmpty;
}
@override
void onSubmit(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
// set values
ref
.read(currentSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
ref
.read(apiEndpointSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
// start search
var doSearch = ref.read(doSearchFunctionProvider);
if (doSearch != null) {
doSearch(context, ref);
} else {
log.d("no doSearch method found!");
}
}
@override
void onLostFocus(BuildContext context, WidgetRef ref,
List<String> searchTermInputContent) {
// set values
ref
.read(currentSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
ref
.read(apiEndpointSearchTermInputContentProvider.notifier)
.setValue(searchTermInputContent);
}
}
BaseClass of the Widget:
abstract class SearchTermInput extends ConsumerStatefulWidget {
const SearchTermInput({super.key});
NotifierProvider? get apiEndpointSearchTermInputContentProvider;
List<String>? get captionList;
List<TextInputFormatter>? get textInputFormatter;
void Function(BuildContext, WidgetRef, List<String>) get onSubmit;
void Function(BuildContext, WidgetRef, List<String>) get onLostFocus;
}
Widget implementation for ApiEndpointName and ApiEndpointUniversal:
class SearchTermInputOneString extends SearchTermInput {
@override
final NotifierProvider apiEndpointSearchTermInputContentProvider;
@override
final List<String> captionList;
@override
final List<TextInputFormatter>? textInputFormatter;
@override
final void Function(BuildContext, WidgetRef, List<String>) onSubmit;
@override
final void Function(BuildContext, WidgetRef, List<String>) onLostFocus;
const SearchTermInputOneString({
super.key,
required this.apiEndpointSearchTermInputContentProvider,
required this.captionList,
required this.textInputFormatter,
required this.onSubmit,
required this.onLostFocus,
});
@override
// ignore: no_logic_in_create_state - this is temporarily for for logging!
ConsumerState<ConsumerStatefulWidget> createState() {
final log = getLogger();
log.t("createState");
return _SearchTermInputOneStringState();
}
}
class _SearchTermInputOneStringState
extends ConsumerState<SearchTermInputOneString> {
late TextEditingController textEditingController;
late List<String> currentContent;
@override
void initState() {
super.initState();
final log = getLogger();
log.t("initstate");
textEditingController = TextEditingController();
}
@override
void didChangeDependencies() {
_runsAfterInit(context, ref);
final log = getLogger();
log.t("didChangeDependencies");
// read apiEndpoint content
currentContent = ref
.read(widget.apiEndpointSearchTermInputContentProvider)
.cast<String>();
textEditingController.text =
currentContent.isNotEmpty ? currentContent[0] : "";
super.didChangeDependencies();
}
@override
void dispose() {
textEditingController.dispose();
final log = getLogger();
log.t("dispose");
super.dispose();
}
Future<void> _runsAfterInit(BuildContext context, WidgetRef ref) async {
await Future.delayed(Duration.zero); // <-- Add a 0 dummy waiting time
final log = getLogger();
log.t("_runsAfterInit");
// set current content
ref
.read(currentSearchTermInputContentProvider.notifier)
.setValue(currentContent);
}
@override
Widget build(BuildContext context) {
return Focus(
child: TextFormField(
controller: textEditingController,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: widget.captionList.isNotEmpty ? widget.captionList[0] : "",
suffixIcon: IconButton(
onPressed: () {
textEditingController.text = "";
},
icon: Icon(Icons.clear),
),
),
inputFormatters: widget.textInputFormatter,
onFieldSubmitted: (_) {
widget.onSubmit(context, ref, [textEditingController.text]);
},
),
onFocusChange: (hasFocus) {
if (!hasFocus) {
widget.onLostFocus(context, ref, [textEditingController.text]);
}
},
);
}
}
Logoutput after the first instance has been created:
────────────────────────────────────────────────────────────────────────────────────────
#0 SearchTermInputOneString.createState (package:obituary_viewer/features/obituaries/presentation/widgets/search_term_inputs/search_term_input_one_string.dart:39:9)
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2024-11-18 08:26:03.262
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
createState
────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────
#0 _SearchTermInputOneStringState.initState (package:obituary_viewer/features/obituaries/presentation/widgets/search_term_inputs/search_term_input_one_string.dart:53:9)
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2024-11-18 08:26:03.269
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
initstate
────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────
#0 _SearchTermInputOneStringState.didChangeDependencies (package:obituary_viewer/features/obituaries/presentation/widgets/search_term_inputs/search_term_input_one_string.dart:61:9)
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2024-11-18 08:26:03.272
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
didChangeDependencies
────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────
#0 ApiEndpointNameSearchTermInputContent.build (package:obituary_viewer/features/obituaries/presentation/provider/search_term_input_content_provider.dart:26:9)
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2024-11-18 08:26:03.275
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
ApiEndpointNameSearchTermInputContent provider build
────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────
#0 DoSearchFunction.build (package:obituary_viewer/features/obituaries/presentation/provider/search_screen_provider.dart:13:9)
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2024-11-18 08:26:03.402
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
DoSearchFunction provider build
────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────
#0 DoSearchFunction.setValue (package:obituary_viewer/features/obituaries/presentation/provider/search_screen_provider.dart:19:9)
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2024-11-18 08:26:03.404
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
DoSearchFunction set to Closure: (BuildContext, WidgetRef) => void from Function 'doSearch':.
────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────
#0 _SearchTermInputOneStringState._runsAfterInit (package:obituary_viewer/features/obituaries/presentation/widgets/search_term_inputs/search_term_input_one_string.dart:85:9)
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2024-11-18 08:26:03.405
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
_runsAfterInit
────────────────────────────────────────────────────────────────────────────────────────
Logoutput after the second instance:
> flutter:
> ┌─────────────────────────────────────────────────────────────────────────────────────────
> flutter: │ #0 CurrentApiEndpoint.setValue
> (package:obituary_viewer/features/obituaries/presentation/provider/api_endpoint_provider.dart:30:9)
> flutter:
> ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
> flutter: │ 2024-11-18 08:27:41.773 flutter:
> ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
> flutter: │ CurrentApiEndpoints set to Instance of
> 'ApiEndpointUniversal' flutter:
> └─────────────────────────────────────────────────────────────────────────────────────────
That's it - no create
, no initState
(what seems to be correct after deleting the unique key), no didChangeDependencies
:( - and the text of the texteditingcontroller is still the one of the first instance :(
I am at the very beginning of my “flutter career” and don't want to learn anything wrong. I am therefore very grateful for your advice!