I want to be able to remove a widget from tree, or remove a child of a widget. I tried to use states to change a widget to null but it's returning an error. Is there a solution ?
Here is the error
https://gist.github.com/litekangel/e2037cf5dc4dbd9c0c0a9860ad3b0270
I finally found a solution to hide/remove a widget : I just replaced it by an empty widget (may be I will add a small animation) but I am still looking for a cleaner way to do this.
In flutter you don't really update a tree of widget you actually generate a new tree every time you need to change it. So you only have to change the returned value of your widget build function.
If you want an empty widget, Container() is a good choice.
Another good approach to replace widgets in the tree is to give your widgets a key.
(Flutter will rebuild the subtree if the key changes.)
So let's say you have a StreamBuilder, and for, whatever reason, need the child widget to be built from scratch every time (maybe due to dependency injection, where one of the dependencies change), you can do this:
StreamBuilder(
stream: bloc.myDependencyChanged, // A hypothetical bloc which notifies when a relevant dependency has changed.
builder: (_, snap) {
final dep = MyChangingDependency();
// MyWidget will NOT get reused by flutter if the key changes.
return MyWidget(dep, key: ValueKey(dep.getId()));
},
);
Related
I would like to check if the user added my widgets to the Home Screen, is there an API for this? I could not find one. WidgetCenter.getCurrentConfigurations returns all available widgets served by the app, not the used ones.
The reasons I look for such an API are:
I would like to report usages of the widgets.
I would like to decide if I should trigger timeline reloads via WidgetCenter when state changes happen in the app.
Method WidgetCenter.shared.getCurrentConfigurations does return the number of user configured widgets:
WidgetCenter.shared.getCurrentConfigurations { widgets
if let widgets = widgets, widgets.count > 0 {
// User did configure at least one widgets
}
}
This is also according the documentation:
Retrieves information about user-configured widgets.
Unfortunately, I don't think such an API exists (yet).
For 1. I would write something that identifies the widget in a shared user defaults container. Hooks for that would be getSnapshot(for:,in:,completion:) or getTimeline(for:,in:,completion:) with context.isPreview == false. Now the difficult part is that you don't get any id for the widget so you cannot distinguish two widgets with the same configuration (afaik).
For 2. I think this is (and will be) opaque, so you just tell the WidgetCenter to reload specific or all configurations and when no widget is currently placed on the home screen nothing happens.
I've been dabbling with flutter for a few days, and I'm trying to make a simple ToDo app, as a learning project. I'm trying to implement something like a BLoC. A list of ListItem widgets is built with ListView.builder, wrapped in StreamBuilder. I have implemented a StreamController'<'List'<'Note'>'>', and whenever I add a new Note to the list, I've managed to add it to a temporary list and then pass the list through the StreamSink, though I suspect it rebuilds the whole ListView each time an item is added.
I'm trying to learn piece by piece, to understand streams in isolation. What is a better way of implementing this? I'm only able to find examples of simple types like Stream but not for complex types like Lists.
class Note {
String title, note;
Note(this.title, this.note);
}
class ListBloc {
final notes = <Note>[];
final _controller = StreamController<List<Note>>.broadcast();
get controllerOut => _controller.stream.asBroadcastStream();
get controllerIn => _controller.sink;
addNewNote(Note note) {
notes.add(note);
controllerIn.add(notes);
}
void dispose() {
_controller.close();
}
}
I'm sure there's a better approach, that will add a new entry to the ListView. I've tried to not use any external packages since I just want to learn the basics.
For adding and removing items from the list, there's nothing wrong with rebuilding the whole list (That's how it's supposed to work).
But, for constantly updating items in the list, you can have a substream for each item to update only that item when it changes.
I read an article by Filip Hracek #filiph that
One disadvantage that stems from the asynchronicity of streams is that when you build a StreamBuilder, it always shows initialData first (because it is available synchronously) and only then does it show the first event coming from the Stream. This can lead to a flash (one frame) of missing data. There are ways to prevent this — stay tuned for a more detailed article.
I am facing this issue, and I need to know the ways to prevent the flash. It would be great if someone knows the way. I am adding new data to my sink, and then accessing my stream builder snapshot to get the data. However, it returns the initial data which is null or some seed value if I use rxdart. I want the latest data, I tried using async- await, but it didn't help. I am setting the snapshot.data value in a Map, with index associated with my itemBuilder.
Here is a sample code
return ListView.builder(
itemBuilder: (context, int index){
return checkboxListTile(
title: Text(xyz)
value: valueMap[key[index]];
onChanged:(value){bloc.myController.sink.add(value);
valueMap[key[index]] = snapshot.data;}
);
}
);
The snapshot.data returns old values. So it basically lags one step. I understand its an asynchronous and synchronous issue. But I need a way around.
In my case it was a hit or miss because I was relying on data being updated by Firestore cloud functions!!!!!!!!!
Depending on how quickly the function executed, the data was not always as expected.
Say I have a custom element, who has a #observable Map model = toObservable({'k': 'v'}); in its dart file, and <span>{{model['k']}}</span> in its html file, when I changed model, how can I know, without using MutationObserver to observe DOM, that the new value is applied to DOM?
You have to use toObservable() on your map, otherwise new values will not be inserted.
Why do you need to know when new values are updated in the DOM? If you really need it you can listen to the changes of the ObservableMap.
You can listen to model.changes but this is also what Polymer does. To execute your code after Polymer added the elements to the DOM you can delay your code like
model.changes.listen((changes) {
new Future(() => doSomethingAfterDomUpdate());
});
This way you give Polymer time to complete its updates.
I made a new widget following the LatestTwitter example from Maarten Balliauw.
My project is an almost exact copy of it, but using diferent namespaces, class names, etc.
I can enable the module and add the widget to the layer.
However, after adding the widget (which generates a sucessful notification message) I can observe that no record has been inserted into the database table that should hold this record.
And when I try to edit the widget I get the error:
NHibernate.MappingException was unhandled by user code
Message=No persister for: MyNamespace.MyWidgetRecord
Source=NHibernate
StackTrace:
at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String entityName)
(...)
How can this problem be solved?
its probably one of the following
hbm.xml not set to embedded resource
MyWidgetRecordMap : Classmap<MyWidgetRecord> not public
hbm or Mapping class not added to the configuration
I ended up rewriting the module from scratch, and now it works. The original problem remains a mistery...