-
-
Notifications
You must be signed in to change notification settings - Fork 240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using SentryAssetBundle() causes asset images to flash when CupertinoContextMenu() tapped #2528
Comments
hey, thanks for the issue does this happen consistently? |
I'm able to reproduce this, thanks for the snippet |
I tried it on a device called "SH M25 (mobile)" and it occurred 100% of the time. |
thanks for the info, we're looking into it |
AssetBundle FlickeringI could reproduce the issue with the code that @kouroku-room provided. I tried to narrow the issue down and implemented some minimal classes of TestsRoot AssetBundleUsing just the root bundle is fine, we do not experience any flickering DefaultAssetBundle(
bundle: rootBundle,
child: MyHomePage(),
) Delegating AssetBundleImplement a class which wraps DefaultAssetBundle(
bundle: DelegatingAssetBundle(rootBundle),
child: MyHomePage(),
)
class DelegatingAssetBundle implements AssetBundle {
final AssetBundle _bundle;
DelegatingAssetBundle(this._bundle);
@override
Future<ByteData> load(String key) {
return _bundle.load(key);
}
@override
Future<ImmutableBuffer> loadBuffer(String key) {
return _bundle.loadBuffer(key);
}
@override
Future<String> loadString(String key, {bool cache = true}) {
return _bundle.loadString(key, cache: cache);
}
@override
Future<T> loadStructuredBinaryData<T>(String key, FutureOr<T> Function(ByteData data) parser) {
return _bundle.loadStructuredBinaryData(key, parser);
}
@override
Future<T> loadStructuredData<T>(String key, Future<T> Function(String value) parser) {
return _bundle.loadStructuredData(key, parser);
}
@override
void evict(String key) {
_bundle.evict(key);
}
@override
void clear() {
_bundle.clear();
}
} Tracing AssetBundleIf we wart the calls and await them, for example to do tracing, we always get flickering. This is basically what we do in DefaultAssetBundle(
bundle: TracingAssetBundle(rootBundle),
child: MyHomePage(),
)
class TracingAssetBundle implements AssetBundle {
final AssetBundle _bundle;
TracingAssetBundle(this._bundle);
@override
Future<ByteData> load(String key) {
return traceAction("load", () => _bundle.load(key));
}
@override
Future<ImmutableBuffer> loadBuffer(String key) {
return traceAction("loadBuffer", () =>_bundle.loadBuffer(key));
}
@override
Future<String> loadString(String key, {bool cache = true}) {
return traceAction("loadString", () => _bundle.loadString(key, cache: cache));
}
@override
Future<T> loadStructuredData<T>(String key, Future<T> Function(String value) parser) {
return traceAction("loadStructuredData", () => _bundle.loadStructuredData(key, parser));
}
@override
Future<T> loadStructuredBinaryData<T>(String key, FutureOr<T> Function(ByteData data) parser) {
return traceAction("loadStructuredBinaryData", () => _bundle.loadStructuredBinaryData(key, parser));
}
@override
void evict(String key) {
traceVoidAction('evict', () => _bundle.evict(key));
}
@override
void clear() {
traceVoidAction('clear', () => _bundle.clear());
}
// Helper
Future<T> traceAction<T>(String traceName, Future<T> Function() action) {
return Future<T>(() async {
print("start trace $traceName");
final data = await action();
print("end trace $traceName");
return data;
});
}
FutureOr<void> traceVoidAction(String traceName, FutureOr<void> Function() action) {
return Future<void>(() async {
print("start trace $traceName");
final data = await action();
print("end trace $traceName");
return data;
});
}
} ConclusionI'm not sure yet how to avoid the flickering, as even the most simple examples produce it. I also don't fully understand yet how just wrapping the root bundle and delegating the calls, without awaiting, is provoking one flicker. The |
Ok, resolved the first issue of Image.asset(
'assets/bottle_1.png',
bundle: DefaultAssetBundle.of(context),
width: 500,
height: 500,
// No flickering occurs when setting scale as shown below.
// scale: 1,
fit: BoxFit.cover,
) |
Found a solution. 🥳 When wrapping the methods, we need to use a completer and find out through control-flow if we are async or sync (cached), that way we do not have the flickering. class TracingAssetBundle implements AssetBundle {
final AssetBundle _bundle;
TracingAssetBundle(this._bundle);
@override
Future<ByteData> load(String key) {
return traceAction("load", _bundle.load(key));
}
@override
Future<ImmutableBuffer> loadBuffer(String key) {
return traceAction("loadBuffer", _bundle.loadBuffer(key));
}
@override
Future<String> loadString(String key, {bool cache = true}) {
return traceAction("loadString", _bundle.loadString(key, cache: cache));
}
@override
Future<T> loadStructuredData<T>(String key, Future<T> Function(String value) parser) {
return traceAction("loadStructuredData", _bundle.loadStructuredData(key, parser));
}
@override
Future<T> loadStructuredBinaryData<T>(String key, FutureOr<T> Function(ByteData data) parser) {
return traceAction("loadStructuredBinaryData", _bundle.loadStructuredBinaryData(key, parser));
}
@override
void evict(String key) {
_bundle.evict(key);
}
@override
void clear() {
_bundle.clear();
}
// Helper
Future<T> traceAction<T>(String traceName, Future<T> future) {
Completer<T>? completer;
Future<T>? result;
print("start trace $traceName");
future.then((data) {
print("end trace $traceName");
if (completer != null) {
completer.complete(data);
} else {
result = SynchronousFuture<T>(data);
}
}).onError((Object error, StackTrace stack) {
completer?.completeError(error, stack);
});
if (result != null) {
return result!;
}
completer = Completer<T>();
return completer.future;
}
} Will create a PR that applies this approach to |
Platform
Flutter Mobile Android
Obfuscation
Disabled
Debug Info
Disabled
Doctor
flutter doctor -v
[√] Flutter (Channel stable, 3.27.0, on Microsoft Windows [Version 10.0.22631.4602], locale ja-JP)
• Flutter version 3.27.0 on channel stable at C:\dev\flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 8495dee1fd (9 days ago), 2024-12-10 14:23:39 -0800
• Engine revision 83bacfc525
• Dart version 3.6.0
• DevTools version 2.40.2
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
• Android SDK at C:\Users\sugur\AppData\Local\Android\sdk
• Platform android-35, build-tools 35.0.0
• Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
• Java version OpenJDK Runtime Environment (build 21.0.3+-12282718-b509.11)
• All Android licenses accepted.
[√] Chrome - develop for the web
• Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.10.1)
• Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
• Visual Studio Community 2022 version 17.10.34928.147
• Windows 10 SDK version 10.0.22621.0
[√] Android Studio (version 2024.1)
• Android Studio at C:\Program Files\Android\Android Studio Koala Feature Drop
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
• Java version openjdk version "17.0.11" 2024-04-16
[√] Android Studio (version 2024.2)
• Android Studio at C:\Program Files\Android\Android Studio
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
• Java version openjdk version "21.0.3" 2024-04-16
[√] VS Code (version 1.95.3)
• VS Code at C:\Users\sugur\AppData\Local\Programs\Microsoft VS Code
• Flutter extension version 3.102.0
[√] Connected device (4 available)
• SH M25 (mobile) • adb-SX3LHMB420105423-rrDg4j._adb-tls-connect._tcp • android-arm64 • Android 14 (API 34)
• Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.22631.4602]
• Chrome (web) • chrome • web-javascript • Google Chrome 131.0.6778.140
• Edge (web) • edge • web-javascript • Microsoft Edge 131.0.2903.99
[√] Network resources
• All expected network resources are available.
• No issues found!
Version
8.11.1
Steps to Reproduce
Probably the same thing is occurring with that issue.
#1457
The above issue is closed because they could not provide reproducible code, but I could create it and will provide it.
https://github.com/kouroku-room/sample_for_issue/tree/9ca1d8f7fc4c7287cb7a96e0d9b4b63e698f6635
Prepare Assets files with different resolutions.
https://docs.flutter.dev/ui/assets/assets-and-images#resolution-aware
Put CupertinoContextMenu(child: Image.asset()).
->At this time, a long press will not cause flickering.
When wrapped in DefaultAssetBundle() with SentryAssetBundle() in place, the image flickers when long pressed.
Expected Result
No image flicker shall occur.
Actual Result
The image flickers when long pressed CupertinoContextMenu().
Are you willing to submit a PR?
None
The text was updated successfully, but these errors were encountered: