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

Observer.optimized #952

Merged
merged 9 commits into from
Nov 19, 2023
Merged

Conversation

subzero911
Copy link
Contributor

I already did a PR #909 but I accidentally deleted the forked repo.
So I made it again and a little bit better.

Mostly you try to make Observer as small as possible. But sometimes you'll want to exclude the widget subtree from re-render and improve the performance.

Real world examples:

  1. You have a colored Container with some heavy widgets inside (like ListView with shrinkWrap: true).
    You want to change the color by Observable, but don't want to rebuild the whole ListView.
  2. You have some fancy animation driven by Observable. You want to animate the widget and want to preserve its children from being rebuilt.

I introduce the new Observer.optimized which allows you to exclude the child branch.
Usage:

Observer.optimized(
  builderOptimized: (context, child) => FooWidget(foo: foo, child: child),
  child: BarWidget(), // is not rebuilt
),

Solves #551

@amondnet @fzyzcjy


Pull Request Checklist

  • If the changes are being made to code, ensure the version in pubspec.yaml is updated.
  • Increment the major/minor/patch/patch-count, depending on the complexity of change
  • Add the necessary unit tests to ensure the coverage does not drop
  • Update the Changelog to include all changes made in this PR, organized by version
  • Run the melos run set_version command from the root directory
  • Include the necessary reviewers for the PR
  • Update the docs if there are any API changes or additions to functionality

Copy link

codecov bot commented Nov 6, 2023

Codecov Report

Merging #952 (bf2623f) into master (7510ee4) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #952   +/-   ##
=======================================
  Coverage   98.99%   98.99%           
=======================================
  Files          57       57           
  Lines        1992     1998    +6     
=======================================
+ Hits         1972     1978    +6     
  Misses         20       20           
Flag Coverage Δ
flutter_mobx 100.00% <100.00%> (ø)
mobx 98.55% <ø> (ø)
mobx_codegen 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
flutter_mobx/lib/src/observer.dart 100.00% <100.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7510ee4...bf2623f. Read the comment docs.

final WidgetBuilder builder;
/// Observer which excludes the child branch
// ignore: prefer_const_constructors_in_immutables
Observer.optimized({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should call this withChild to make the intent clear. The idea is to only build parts that are actually changing and keeping rest of the tree intact. I think you would also need a withChildren variant as well which could be a Map<String, Widget>?. This variant will help in plugging in parts of the tree which are not changing. This is useful when you have more than one child.

@subzero911
Copy link
Contributor Author

subzero911 commented Nov 19, 2023

@pavanpodila done. I renamed .optimized to .withChild and builderOptimized to builderWithChild
I have no idea how to implement "withChildren" constructor to "exclude subtrees by map keys", and I don't think we actually need it. You can use a Column(children: [...]) as a child, or you can use a composition of Observers.

I applied the same technique which was used in AnimatedBuilder, and provider's Consumer and Selector - they all have the child parameter only. Refer to https://api.flutter.dev/flutter/widgets/AnimatedBuilder-class.html , "Performance optimizations" for details. They don't have any multiple children version.

@pavanpodila pavanpodila merged commit 4e612a8 into mobxjs:master Nov 19, 2023
8 checks passed
@pavanpodila
Copy link
Member

@all-contributors add @subzero911 for code

Copy link
Contributor

@pavanpodila

@subzero911 already contributed before to code

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.

2 participants