'controller != null' error
Describe the bug
With the new structure in v5 I get these kind of errors now and then
ββββββββ Exception caught by widgets library βββββββββββββββββββββββββββββββββββ
The following assertion was thrown building Expanded(flex: 1):
Please register [ShowcaseView] first by calling [ShowcaseView.register()]
Failed assertion: line 177 pos 7: 'controller != null'
This is probably because there seems to be no way to detect if the controller is loaded. So it happens that the guidedtour starts when the showcaseview does not have its controller ready.
Maybe the register function should be async or have a callback when ready so you know it is safe to start the tour.
To Reproduce Steps to reproduce the behavior:
@override
void initState() {
super.initState();
ShowcaseView.register(
disableMovingAnimation: true,
onFinish: () {
guidedTourCompleter.complete();
},
);
WidgetsBinding.instance.addPostFrameCallback((_) {
startGuidedTour();
});
}
Hey @basvdijk
Could you please share a complete, minimal code snippet that reproduces this issue? I tested the code you provided inside the packageβs example app, but I wasnβt able to trigger the same behaviour.
@vasu-nageshri that is a bit of a problem because it is triggered when navigating between views or have popup dialogs. I will see what I can do. Please not that this does not happen when I use the "old style" Where you wrap your entire build tree.
Hi @basvdijk ,
I tested this using the code from the following gist:
π Gist: Example code
I tried it specifically during the pop-up flow, and everything is working correctly on my end in the example setup.
To help identify the issue, could you please share the exact part of your implementation where itβs breaking?
A small reproducible snippet or the widget tree would be really helpful.
Thanks a lot!
@vasu-nageshri The issue is that I can't share my code since it is part of bigger project. So I need to see if I can subtract a part which has the same bug. This will take quite some time.
I want to add that the same thing happens to me. You can have a list of objects where the first object is a ShowCase. Then, you have another route with a tutorial as well. You switch to that one and come back and it happens
@StevenMaMei, Could you please provide a minimal code sample to reproduce the issue so we can investigate and fix it if needed?
@vasu-nageshri Iβm experiencing this same issue as well. Itβs inconsistent and difficult to reproduce, but it does happen occasionally. Unfortunately, I canβt determine the exact cause β Iβm not unregistering the instance anywhere, yet the problem still occurs.
Below is a simplified version of my code (from a much larger project).
Please note: openFeatureTourBottomSheet() simply opens a bottom sheet where the user can either start the showcase tour
by calling ShowcaseView.get().startShowCase([showCaseKey]);
or skip it entirely by popping the sheet Navigator.of(context).pop();
final homeViewModelProvider = Provider<HomeViewModel>((ref) => HomeViewModel());
class HomeViewModel {
bool isGuestUser() => false;
Future<void> authenticate() async {}
Future<void> openFeature(BuildContext context) async {}
}
class HomeScreenBodyV2 extends ConsumerStatefulWidget {
const HomeScreenBodyV2({super.key});
@override
ConsumerState<HomeScreenBodyV2> createState() => _HomeScreenBodyV2State();
}
class _HomeScreenBodyV2State extends ConsumerState<HomeScreenBodyV2> {
final _refreshController = RefreshController();
final featureShowcaseKey = GlobalKey();
@override
void initState() {
super.initState();
ShowcaseView.register(blurValue: 1);
WidgetsBinding.instance.addPostFrameCallback((_) {
_init();
});
}
Future<void> _init() async {
await Future.delayed(const Duration(milliseconds: 300));
openFeatureTourBottomSheet();
}
@override
Widget build(BuildContext context) {
final vm = ref.read(homeViewModelProvider);
return Scaffold(
appBar: AppBar(title: const Text("Showcase Test Example")),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Showcase(
key: featureShowcaseKey,
title: "New Feature",
description: "Tap to open this new feature.",
targetPadding: const EdgeInsets.all(8),
targetBorderRadius: BorderRadius.circular(50),
overlayColor: Colors.black,
overlayOpacity: 0.7,
showArrow: true,
disposeOnTap: true,
onTargetClick: () async {
ShowcaseView.get().dismiss();
await vm.openFeature(context);
},
child: const FloatingActionButton(
onPressed: null,
child: Icon(Icons.star),
),
),
],
),
body: const Center(
child: Text("Content Here"),
),
);
}
}
Hi @AliaaIbrahemAhmed,
I am unable to reproduce the issue you mentioned. I tried running the code you provided, and it works correctly on my end. Iβve attached a screen recording for your reference.
So far, I still cannot reproduce the issue reported by you and @basvdijk :)
https://github.com/user-attachments/assets/8bd3df26-a790-4944-bac8-829cf8d86c00