Event batching

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Event batching

Andrea Aime-2
Hi,
I have a situation that I can't handle in the best way.
I have an event list that's already attached to a table model
and a selection model. Sometimes it happens I have to perform
extensive modification on its contents, but I don't want it
to send events during the operation, they just slow down things...
is there any way to stop event notification and send events about
the differences between the initial and final state?

Best regards
Andrea Aime


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Event batching

Jesse Wilson

Hey Andrea --

On 28-Jul-05, at 1:19 AM, Andrea Aime wrote:
> I have an event list that's already attached to a table model
> and a selection model. Sometimes it happens I have to perform
> extensive modification on its contents, but I don't want it
> to send events during the operation, they just slow down things...
> is there any way to stop event notification and send events about
> the differences between the initial and final state?


There is such a way! Create a class called umm BatchingList,
that looks like so:

public class BatchingList extends TransformedList {
     public BatchingList(EventList source) {
         super(source);
         source.addListEventListener(this);
     }
     public void listChanged(ListEvent e) {
         updates.forwardEvent(e);
     }
     protected boolean isWritable() {
         return true;
      }
     public void beginBatch() {
          updates.beginEvent(true);
     }
     public void commitBatch() {
          updates.commitEvent();
     }
}

Then when you're doing your changes, perform the changes
on the BatchingList:
     EventList myList = new BasicEventList();
     myList.add("A"); // event fired
     myList.add("B"); // event fired
     myList.add("C"); // event fired
     BatchingList myBatchingList = new BatchingList(myList);
     myBatchingList.add("C"); // event fired
     myBatchingList.add("D"); // event fired
     myBatchingList.beginBatch();
     myBatchingList.add("E");
     myBatchingList.remove("A");
     myBatchingList.add("F");
     myBatchingList.commitBatch(); // event fired

All EventLists that use myBatchingList as a source will only
receive events when you call commitBatch(). Therefore you'll
probably want your BatchingList as the first list in your pipeline.

Now for some caveats - beware!
  - Every EventList & model that depends on myBatchingList
    is in an inconsistent state while myBatchingList is mid-change.
    This is because they have state that depends on what myBatchingList
    looks like, and by not firing an event you are allowing that  
state to
    get out of date. Therefore you may never access another EventList or
    model between BatchingList.beginEvent() and  
BatchingList.commitBatch().
    Usually this happens when you always call begin() and commit() in
    pairs, and hold a write lock from before beginBatch() until after
    commitBatch().

  - commitBatch() with no begin will throw an IllegalStateException
  - if you fail to commitBatch() for a batch started with beginBatch(),
    you'll never ever fire an event from that list and you'll see  
lots of
    problems when the dependent lists try to read your BatchList

This is an advanced technique because it allows you, the API user,
to temporarily put an EventList into a state that is inconsistent with
what its observers expect. But it can be very effective so that such
observers do not see any intermediate states. It can be very useful
for your table's rows to go from { X, 1, 2, 3 } to { Y, 4, 3, 2, 1 }  
in a single
event, although there's no single-step List method to perform this
change.

Cheers,
Jesse


smime.p7s (3K) Download Attachment