Skip to content
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

♻️ Split AssetGridItemBuilder to solve the rebuild issue #128

Merged
merged 7 commits into from
May 11, 2021

Conversation

AlexV525
Copy link
Member

@AlexV525 AlexV525 commented May 11, 2021

Resolves #127 .

This is a minimum solution to solve the issue directly, without any breaking changes.

@AlexV525
Copy link
Member Author

Actually the loadMoreAssets method didn't called multiple times.

I/flutter (25101): Loading more assets with page 1: 2021-05-11 11:59:40.085985
I/flutter (25101): Loading more assets with page 2: 2021-05-11 11:59:42.464812
I/flutter (25101): Loading more assets with page 3: 2021-05-11 11:59:44.597433
I/flutter (25101): Loading more assets with page 4: 2021-05-11 11:59:47.431908
I/flutter (25101): Loading more assets with page 5: 2021-05-11 11:59:49.276166
I/flutter (25101): Loading more assets with page 6: 2021-05-11 11:59:52.039088

@yanivshaked
Copy link
Contributor

Testing

@yanivshaked
Copy link
Contributor

yanivshaked commented May 11, 2021

Looks good.
In term of performance, it is better to use SliverGrid instead of GridView.builder.
The reason for that is that when the grid has to repaint itself, you can "teach" the SliverGrid how to find the elements from the previously painted grid using findChildIndexCallback. That cannot be done in the case of GridView.builder (which is specific implementation of SliverGrid).

See:
https://stackoverflow.com/a/58991316/6535274

https://medium.com/flutter/slivers-demystified-6ff68ab0296f

@yanivshaked
Copy link
Contributor

Picker is broken now:

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building Selector<DefaultAssetPickerProvider, bool>(dirty,
dependencies: [_InheritedProviderScope], state:
_Selector0State#ce087(value: true)):
Tried to use context.select outside of the build method of a widget.

Any usage other than inside the build method of a widget are not supported.
'package:provider/src/inherited_provider.dart':
Failed assertion: line 246 pos 12: 'widget is LayoutBuilder || debugDoingBuild'

The relevant error-causing widget was:
Selector<DefaultAssetPickerProvider, bool>
file:https:///C:/dev/12Tech12/git/pull-requests/12Tech12/flutter_wechat_assets_picker/lib/src/delegates/asset_picker_builder_delegate.dart:520:13

When the exception was thrown, this was the stack:
#2      SelectContext.select (package:provider/src/inherited_provider.dart:246:12)
#3      DefaultAssetPickerBuilderDelegate.pathEntityListWidget (package:wechat_assets_picker/src/delegates/asset_picker_builder_delegate.dart:917:17)
#4      DefaultAssetPickerBuilderDelegate.androidLayout.<anonymous closure> (package:wechat_assets_picker/src/delegates/asset_picker_builder_delegate.dart:542:23)
#5      _Selector0State.buildWithChild (package:provider/src/selector.dart:85:29)
#6      SingleChildState.build (package:nested/nested.dart:317:41)
#7      StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
#8      SingleChildStatefulElement.build (package:nested/nested.dart:339:18)
#9      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4495:15)
#10     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4667:11)
#11     Element.rebuild (package:flutter/src/widgets/framework.dart:4189:5)
#12     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2694:33)
#13     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:873:21)
#14     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5)
#15     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
#16     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1082:9)
#17     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:998:5)
#21     _invoke (dart:ui/hooks.dart:161:10)
#22     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:253:5)
#23     _drawFrame (dart:ui/hooks.dart:120:31)
(elided 5 frames from class _AssertionError and dart:async)

@AlexV525 AlexV525 marked this pull request as draft May 11, 2021 06:31
@AlexV525 AlexV525 marked this pull request as ready for review May 11, 2021 06:38
@AlexV525
Copy link
Member Author

Take another look.

@yanivshaked
Copy link
Contributor

yanivshaked commented May 11, 2021

I am constantly checking :-)

While performance is better scrolling down (due to findChildIndexCallback), there is now an issue when scrolling up (that did NOT exist with GridView.builder).
Scrolling up shows black grid items for a moment.

@AlexV525
Copy link
Member Author

I am constantly checking :-)

While performance is better scrolling down (due to findChildIndexCallback), there is now an issue when scrolling up (that did NOT exist with GridView.builder).
Scrolling up shows black grid items for a moment.

It should be, otherwise items are still keepalive which makes Flutter unable to release memory cost for those images.

@yanivshaked
Copy link
Contributor

It should be, otherwise items are still keepalive which makes Flutter unable to release memory cost for those images.

But addAutomaticKeepAlives default to true, shouldn't that do the trick?

In any case I think this is worse in term of user experience, previous experience was better.

@yanivshaked
Copy link
Contributor

Maybe there an option to extend the preloading of items?

@AlexV525
Copy link
Member Author

previous experience was better.

"Previous" only indicates the commit in this PR. Originally it does act like that too. The automatic keepalives flag isn't the same thing as a Widget does itself.

@yanivshaked
Copy link
Contributor

Correct, that is what I meant. Previous = after the split.

@AlexV525
Copy link
Member Author

Going deeper, it's some GC trick that came from extended_image. So for now I would not recommend to commit that behavior.

@yanivshaked
Copy link
Contributor

I agree, better go back to GridView.builder.

@yanivshaked
Copy link
Contributor

Sorry for that...

@AlexV525
Copy link
Member Author

I mean we keep this since we can ensure that it won't cost more memory consumption.

@yanivshaked
Copy link
Contributor

The tradeoff of optimize memory save optimize speed will always be there.
Is there some way to preload the assets in the SliverGrid case so that it will be less visible to the user?

@AlexV525
Copy link
Member Author

Have you registered with Discord? You can add me Alex Li (AlexV525)#3670 then we can discuss about this.

@yanivshaked
Copy link
Contributor

Friend request sent

@AlexV525 AlexV525 merged commit 8f9faec into master May 11, 2021
@AlexV525 AlexV525 deleted the fix-rebuild-issue branch May 11, 2021 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Optimize scrolling] Scrolling of grid shows black/empty items
2 participants