The order in which observers are activated


#1

Am I correct?
I thought the observers added to the model are activated in sequence depending on their function.
In my script I have “EntitiesObserver” with “onElementAdded” and “onElementModified” methods, and “ModelObserver” with the “onTransactionUndo” method. I wanted “onTransactionUndo” to be activated before “onElementModified”, and I got it by adding “ModelObserver” to the model before the “EntitiesObserver” to the model entities. As for “onElementAdded”, for example, if a user makes only one copy of the component or 10 (Array), I want “onElementAdded” to collect all the new components and then work on them when that user’s operation is over. So I added another “ModelObserver” with the “onTransactionCommit” method BUT AFTER “EntitiesObserver”. And that also works for me!
Do I need to consider something or is this okay?


#2

It sounds like what you want to achieve requires many assumptions (things that may work but are not specified and guaranteed by the API). So make sure to do defensive programming, i.e. check that your assumptions are true (using if conditions, e.g. check if a reference that can be nil really holds the expected value).

I was not under the impression that observers are executed globally in the sequence as they were registered (I was thinking at most in the order for the specific type of observer on that specific entity). The API specifies only little about the order of execution of observers, they depend on the internal implementation of SketchUp, so treat them as if they were concurrent.

Since the array copy is not directly accessible through the API (you can not directly observe it), I can understand your approach.

  • We can assume that between a onTransactionStart and onTransactionCommit is a transaction/operation, but it can be any operation. Also, component instances can be added by other operations and extensions. So if possible, check that onElementAdded and onTransactionCommit are caused by the desired tool, e.g. if model.tools.active_tool_id / …name is the Move Tool or Rotate Tool (and even then, another extension could have triggered it).
  • There can be nested operations. I don’t know what implications they have on this solution.
  • If one of your observers stores its result in a shared variable (instance variable) and another of your observers accesses the result, ensure that no error is raised if the first observer was not triggered for whatever reason.

#3

Thanks Aerilius!
It does not matter to me which tool and what change has been made. It is only important to me that my script begins to perform its function after the user makes the changes to one or more components or groups. But yes … you’re right! The problem is that there may be several nested operations. I could set a short timer to find out if a new operation started. Is that right? If there are multiple operations by one user action, a short timer would be sufficient to delay my operation before others finish.

… But now I realized that this is not good if someone does the same thing as me :).
Nevermind! I’ll figure something out!
Thanks again!


#4

How short? And what if it is too long? A timer is asynchronous, and since not synchronous/sequential, it can never guarantee to solve sequential problems. While you can parametrize the duration so it works for most human interactions, a transaction is much shorter (a couple of lines of code are executed very, very fast, and depend on the user’s CPU).

You could maintain a counter of the operation nesting level that is increased/decreased by start/commit of operations.


#5

There is some help in SketchUp’s GitHub repos for observers …
you look it over and decide if it applies to this situation.


#6

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.