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

Have an something that extends ValueNotifier or ValueListenable for a ValueListenableBuilder #20

Closed
mikuhl-dev opened this issue Aug 18, 2019 · 18 comments
Labels
enhancement New feature or request

Comments

@mikuhl-dev
Copy link

This way you can have a widget update when the value of a certain key updates!

@simc
Copy link
Member

simc commented Aug 19, 2019

You can just use something like this:

var box = Hive.box('yourBox');
box.watch('yourKey').listen((e) {
  setState(() {});
});

This will update your widget when yourKey changes.

@mikuhl-dev
Copy link
Author

setState is not the best practice though, often rebuilds more than what you need.

@simc
Copy link
Member

simc commented Aug 19, 2019

Could you provide a sample of what you have in mind?

@mikuhl-dev
Copy link
Author

mikuhl-dev commented Aug 19, 2019

Maybe like

HiveListenable darkMode = HiveListenable(myBox, 'darkMode');

and

ValueListenableBuilder(
  valueListenable: darkMode,
  builder: (BuildContext context, bool darkMode, Widget child) {
    return ListTile(
      title: child,
      trailing: Switch(
        value: darkMode,
        onChanged: (bool changed) {
          myBox.put('darkMode', changed);
          // Or maybe this.darkMode.set(changed);
        },
      ),
    );
  },
  /*
    For this example, Text isnt that expensive,
    but you can put more expensive widgets here
    and they wont constantly rebuild when you want to
    change JUST the switch.
  */
  child: Text('Dark Mode'),
),

@simc
Copy link
Member

simc commented Aug 19, 2019

I understand, thanks...

@simc
Copy link
Member

simc commented Aug 19, 2019

I created the HiveBuilder how do you like it?

Here is a simple example how it works.

@mikuhl-dev
Copy link
Author

I was thinking like this:

class HiveNotifier extends ValueNotifier {

  final Box box;
  final String key;
  
  HiveNotifier(this.box, this.key) : super(box.get(key)) {
    box.watch(key: key).listen((BoxEvent event) {
      if (event.value == value) return;
      value = event.value;
    });
  }

  @override
  get value => box.get(key);

  @override
  set value(newValue) {
    box.put(key, value);
    notifyListeners();
  }

}

Didn't try to see if it works though.

@haroldolivieri
Copy link

haroldolivieri commented Aug 30, 2019

IMHO, I don’t think you need more than Hive.watch. You can extend its usage for your own specific implementation (Provider, ScopeModel, InheritedWidget, StreamBuilder).

In my case, I am creating a stream from Hive.watch so I can use a StreamBuilder to observe state changes on specific widgets.

  Stream<List<String>> watchChanges() {
    return Hive.box(boxNameKey)
        .watch(key: recentQueriesKey)
        .map((event) => fetchQueries());
  }

You can create your own ChangeNotifier and observe changes with watch to notifyListeners().

But what I really think is this watch should return the initial value when we listen to a specific key. Currently I have to watch changes and do a separate fetch to receive all values since the very beginning.

@simc
Copy link
Member

simc commented Aug 30, 2019

IMHO, I don’t think you need more than Hive.watch. You can extend its usage for your own specific implementation (Provider, ScopeModel, InheritedWidget, StreamBuilder).

I agree.

But what I really think is this watch should return the initial value when we listen to a specific key. Currently I have to watch and map to receive all values since the very beginning.

I don't quite undestand what you mean. Do you want to receive all events for a key since the box has been opened? Hive would need to keep them for any key in case you watch that key anytime later.

@haroldolivieri
Copy link

haroldolivieri commented Aug 30, 2019

Sorry, I’ve updated my comment.

I would like that watch had a seedValue for the time I subscribe to it, but only when I am listening to a specific key, like a snapshot.

Otherwise I have to do listen and fetch for the first content not be null, as you do on WatchBoxWidget, this shouldn’t be necessary.

@simc
Copy link
Member

simc commented Aug 30, 2019

You are right, the reason why I didn't implement that are lazy boxes.

Since lazy boxes don't keep the values in memory, they would need to be fetched for each subscribe call.

I'm not sure how to solve this.
Edit: Maybe using a sendInitialEvent parameter for the watch() method. What do you think?

@haroldolivieri
Copy link

haroldolivieri commented Aug 30, 2019

What about an optional param where we can ask for this initialValue? So it would not be a problem to fetch it again for lazyBox under the hood as in cases like mine we will have to fetch it anyway.

@haroldolivieri
Copy link

Hahah exactly

@simc
Copy link
Member

simc commented Aug 30, 2019

Okay let's do that 👍

@simc simc added the enhancement New feature or request label Sep 17, 2019
@simc simc added this to the Near-term Goals milestone Oct 11, 2019
@simc
Copy link
Member

simc commented Dec 31, 2019

This has finally been implemented:

ValueListenableBuilder(
  valueListenable: Hive.box('settings').listenable(),
  builder: (context, box, widget) {
    return Center(
      child: Switch(
        value: box.get('darkMode', defaultValue: false),
        onChanged: (val) => box.put('darkMode', val),
      ),
    );
  },
)

@simc simc closed this as completed Dec 31, 2019
@mikuhl-dev
Copy link
Author

Thanks @leisim! Hopefully we can get key listeners too because I would rather widgets not rebuild when an irrelevant setting changes.

@simc
Copy link
Member

simc commented Dec 31, 2019

@MichaelPriebe You can use yourBox.listenable(key: 'someKey')

@mikuhl-dev
Copy link
Author

mikuhl-dev commented Dec 31, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants