get_it_mixin icon indicating copy to clipboard operation
get_it_mixin copied to clipboard

`Watch` does not trigger rebuild

Open CaptainDario opened this issue 3 years ago • 13 comments

I have a custom object Strokes which implements changeNotifier. I watch it with:

final Strokes strokes = watchOnly((Strokes s) => s);

This object has two methods deleteLastStroke():

    // get all strokes except for the last one
    var p = _path.computeMetrics().take(_path.computeMetrics().length - 1);
    var newPath = Path();
    // copy the strokes to a new Path
    p.forEach((element) {
      newPath.addPath(element.extractPath(0, double.infinity), Offset.zero);
    });
    _path = newPath;

    decrementStrokeCount();

    notifyListeners();

and deleteAllStrokes():

    _path.reset();
    _strokeCount = 0;

    notifyListeners();

Both of them call notifyListeners() however only deleteAllStrokes() triggeres a rebuild of the UI. When calling deleteLastStroke() nothing happens. However when doing:

deleteLastStroke();
setState((){});

The UI rebuilds and everything works as expected.

If I am doing something wrong could you please point me in the right direction?

CaptainDario avatar May 18 '21 07:05 CaptainDario

did you find the problem?

escamoteur avatar May 21 '21 06:05 escamoteur

No, but I think it was a problem with how I used the library. I switched to provider and therefore closed this issue.

CaptainDario avatar May 31 '21 09:05 CaptainDario

ok, sorry I couldn't help you quicker

escamoteur avatar May 31 '21 10:05 escamoteur

Same.

// doesn't rebuild
Widget build(BuildContext context) {
    final notifier = watchOnly((SomeChangeNotifier v) => v);
    ...
// rebuild
Widget build(BuildContext context) {
    final someField = watchOnly((SomeChangeNotifier v) => v.someField);
    ...

t1ooo avatar Mar 22 '22 07:03 t1ooo

I think you would need to implement Equatable for this to work. It's watching the results of the method, and rebuilding when the results change. So it needs oldV != v for rebuild to trigger.

@escamoteur Does this package even support watching an entire ChangeNotifer? I assumed it did, but maybe I was wrong.

esDotDev avatar Mar 22 '22 18:03 esDotDev

Sure it does. I m currently only on my phone. Am 22. März 2022, 19:10 +0100 schrieb Shawn @.***>:

I think you would need to implement Equatable for this to work. It's watching the results of the method, and rebuilding when the results change. @escamoteur Does this package even support watching an entire ChangeNotifer? I assumed it did, but maybe I was wrong. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

escamoteur avatar Mar 24 '22 15:03 escamoteur

@escamoteur

I just tested. It doesn't work if watchOnly returns a ChangeNotifer. It only works when watchOnly doesn't return the ChangeNotifer instance.

final count = watchOnly((MyChangeNotifier myChangeNotifier) => myChangeNotifier.count, instanceName: "myChangeNotifier"); // triggers build on change
final myChangeNotifier = watchOnly((MyChangeNotifier myChangeNotifier) => myChangeNotifier, instanceName: "myChangeNotifier"); // doesn't trigger build on change

FabianTerhorst avatar May 24 '22 09:05 FabianTerhorst

Working workaround:

class _Wrapper<T> {
  final T _value;
  const _Wrapper(this._value);
}
final count = watchOnly((MyChangeNotifier myChangeNotifier) => _Wrapper(myChangeNotifier), instanceName: "myChangeNotifier")._value;

FabianTerhorst avatar May 24 '22 09:05 FabianTerhorst

Sure it does. I m currently only on my phone. Am 22. März 2022, 19:10 +0100 schrieb Shawn @.>: I think you would need to implement Equatable for this to work. It's watching the results of the method, and rebuilding when the results change. @escamoteur Does this package even support watching an entire ChangeNotifer? I assumed it did, but maybe I was wrong. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.>

Can we see an example of how to watch an entire ChangeNotifier ?

Andrius0124 avatar Nov 30 '22 04:11 Andrius0124

Working workaround:

class _Wrapper<T> {
  final T _value;
  const _Wrapper(this._value);
}
final count = watchOnly((MyChangeNotifier myChangeNotifier) => _Wrapper(myChangeNotifier), instanceName: "myChangeNotifier")._value;

for this to work I had remove _value in the end of watchOnly. As _value was retaining the same hashcode

class WatchWrapper<T> {
  final T _value;
  WatchWrapper(this._value);
  T get value => _value;
}
var env = watchOnly((EnvironmentModel m) => WatchWrapper(m));

env.value.something 

Andrius0124 avatar Nov 30 '22 05:11 Andrius0124

Issue still exists. @escamoteur can you please fix it? 😃

capgeti avatar May 24 '23 18:05 capgeti

I had to check in the source, but IMHO if you just pass null for the selector function it will watch the full ChangeNotifier. I'm currently working on the successor to that package and will try to make the API easier.

grafik

check out https://github.com/escamoteur/watch_it/issues/1

escamoteur avatar May 25 '23 06:05 escamoteur

I recomment switching to my new package watch_it

escamoteur avatar Aug 31 '23 07:08 escamoteur