BaseObservableList

Richard Bair richard.bair at oracle.com
Fri Dec 16 16:22:44 PST 2011


Hi Martin,

> Hello,
> I'm working on http://javafx-jira.kenai.com/browse/RT-15029 and as part of this effort, I'm doing a refactoring of ObservableListWrapper.
> 
> So I've created an abstract class BaseObservableList (extends AbstractList) that could serve as a base class for all ObservableLists implementations.

OK, the "Base" naming convention is one that I really regret, I wish we had just done AbstractFoo. Oh well. The things you end up regretting are often not the things you thought you might :-) But the "Base" convention we're using (hopefully everywhere...) is FooBase rather than BaseFoo, so I guess this should be ObservableListBase.

> For a simple (modifiable) implementation, one would need to implement following methods:
> 
>    public int size() {
>    }
> 
>    public E get(int index) {
>    }
> 
>    protected void doAdd(int index, E element) {
>    }
> 
>    protected E doRemove(int index) {
>    }
> 
>    protected E doSet(int index, E element) {
>    }
> 
> 
> 
> So something like ObservableListWrapper would look like this:

Is the proposal also to make ObservableListWrapper public?

> Now when somebody would want to override something else or extend the implementation, an IterableChangeBuilder, that's used in BaseObservableList, needs to be used for this purpose.
> 
> So when creating something by delegating to the methods from the List, you just need to wrap the block in
> changeBuilder.beginComplexChange(); and changeBuilder.endComplexChange();
> This builds up the change in the calls in between instead of calling the observers multiple times.
> 
> E.g. setAll method works like this
> 
>    public boolean setAll(Collection<? extends E>  col) {
>        changeBuilder.beginComplexChange();
>        clear(); //does not call ListChangeListeners
>        addAll(col); //neither does this
>        changeBuilder.endComplexChange(); //this calls the ListChangeListeners using just one Change object
>        return true;
>    }
> 
> 
> On the other hand, if you want to override something simple like add/remove/set or use just doSet, doAdd and doRemove methods or you directly manipulate with your data structure, you have to use a different pattern and use methods from the IterableChangeBuilder (there are methods like nextAdd, nextRemove, nextSet). And then end it with commit() call.
> 
> So, e.g. you want to implement some fast clear() (the original clear in AbstractList iterates over the elements and remove them one by one, building up the resulting change on the way), you would do:
> 
> public void clear() {
>    //do the fast clear
>    changeBuilder.nextRemove(0, listOfRemovedItems);
>    changeBuilder.commit(); //Calls the ListChangeListeners, but only if not in ComplexChange block
> }
> 
> 
> Of course, these 2 patterns could be combined and you can do something like this:
> 
> changeBuilder.beginComplexChange();
> clear(); //no call to observers, as we are in ComplexChange block.
> // do some stuff using doAdd or by directly changing my data structures
> chnageBuilder.nextAdd(0, x); //I've added something so I need to report this
> changeBuilder.endComplexChange(); //calls the ListChangeListeners
> 
> 
> What do you think about this API?

Why is it called an IterableChangeBuilder? Is there a complete description of the API I can see (maybe attach to the issue?).

Thanks!
Richard


More information about the openjfx-dev mailing list