Problem
The static methods DevicePreview.showToolbar() and DevicePreview.hideToolbar() throw an assertion error when called from event handlers (e.g., button onPressed, switch onChanged) because they call Provider.of<DevicePreviewStore>(context) without the listen: false parameter.
Error Message
Tried to listen to a value exposed with provider, from outside of the widget tree.
This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing `listen: false`.
To fix, write:
Provider.of<DevicePreviewStore>(context, listen: false);
Failed assertion: line 308 pos 7: 'context.owner!.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate'
Current Code (Buggy)
In lib/src/device_preview.dart:
Line 245 - showToolbar() method:
static void showToolbar(
BuildContext context, {
bool enablePreview = true,
}) {
final store = Provider.of<DevicePreviewStore>(context); // ❌ Missing listen: false
store.data = store.data.copyWith(
isToolbarVisible: true,
isEnabled: enablePreview,
);
}
Line 257 - hideToolbar() method:
static void hideToolbar(
BuildContext context, {
bool disablePreview = true,
}) {
final store = Provider.of<DevicePreviewStore>(context); // ❌ Missing listen: false
store.data = store.data.copyWith(
isToolbarVisible: false,
isEnabled: !disablePreview,
);
}
Inconsistency
Other static methods in the same file correctly use listen: false:
Line 271 - selectDevice() method (correct):
static void selectDevice(
BuildContext context,
DeviceIdentifier deviceIdentifier,
) {
final store = Provider.of<DevicePreviewStore>(context, listen: false); // ✅ Correct
store.selectDevice(deviceIdentifier);
}
Suggested Fix
Add listen: false to both methods:
static void showToolbar(
BuildContext context, {
bool enablePreview = true,
}) {
final store = Provider.of<DevicePreviewStore>(context, listen: false);
store.data = store.data.copyWith(
isToolbarVisible: true,
isEnabled: enablePreview,
);
}
static void hideToolbar(
BuildContext context, {
bool disablePreview = true,
}) {
final store = Provider.of<DevicePreviewStore>(context, listen: false);
store.data = store.data.copyWith(
isToolbarVisible: false,
isEnabled: !disablePreview,
);
}
Steps to Reproduce
- Create a button or switch in your Flutter app
- Call
DevicePreview.showToolbar(context) or DevicePreview.hideToolbar(context) from the onPressed/onChanged handler
- Observe the assertion error
Example Code That Fails
Switch(
value: isToolbarVisible,
onChanged: (value) {
if (value) {
DevicePreview.showToolbar(context); // ❌ Throws assertion error
} else {
DevicePreview.hideToolbar(context); // ❌ Throws assertion error
}
},
)
Environment
- device_preview: ^1.3.1
- Flutter: 3.x
- Dart: 3.x
Workaround
Currently, developers must directly access the Provider with listen: false:
final store = Provider.of<DevicePreviewStore>(context, listen: false);
store.data = store.data.copyWith(isToolbarVisible: value, isEnabled: value);
This is a simple fix that would make the API consistent with other methods and prevent runtime errors.
Problem
The static methods
DevicePreview.showToolbar()andDevicePreview.hideToolbar()throw an assertion error when called from event handlers (e.g., buttononPressed, switchonChanged) because they callProvider.of<DevicePreviewStore>(context)without thelisten: falseparameter.Error Message
Current Code (Buggy)
In
lib/src/device_preview.dart:Line 245 -
showToolbar()method:Line 257 -
hideToolbar()method:Inconsistency
Other static methods in the same file correctly use
listen: false:Line 271 -
selectDevice()method (correct):Suggested Fix
Add
listen: falseto both methods:Steps to Reproduce
DevicePreview.showToolbar(context)orDevicePreview.hideToolbar(context)from theonPressed/onChangedhandlerExample Code That Fails
Environment
Workaround
Currently, developers must directly access the Provider with
listen: false:This is a simple fix that would make the API consistent with other methods and prevent runtime errors.