Loading Old Objects
It's important to be mindful of the state when writing any class that will be saved in users' drawings. Any fields in a class, particularly public fields, need to be handled properly on load. If fields are added, they will need to be initialized with a default in drawings that predate them. (Note that since bools default to false, this can be used to check for whether a drawing postdates the change.) Similarly, if a field is renamed or converted, you have to handle the old value.
It's harder to correct bad design decisions that have been saved in user drawings than in objects that only exist during runtime, such as Animations. Plan accordingly. It's better to have to rebuild a few objects at load time than to get stuck reverse-engineering what obsolete or contradictory values were supposed to mean when a drawing was saved.
Load Hooks
As Snappers are loaded, a couple of hooks are run to handle loading problems.
loaded0
public Object loaded0(ObjectFormatter formatter, LoadFailInfo failInfo) { // ... }
loaded0
is run as the Snapper is streamed from the file, but before all Snappers have necessarily been loaded. (If the hook depends on neighboring snappers, it should be done in loaded1 instead.) loaded0()
is usually the correct place to initialize/convert fields that have been added or changed.
The return value of loaded0()
is the object itself, and loaded0()
must call its super().
Also, note that the order loaded0()
is run on the world's Snappers is effectively non-deterministic - no code should be written that expects them to be handled in a specific order.
loaded1
public void loaded1(ObjectFormatter formatter, LoadFailInfo failInfo) { // ... }
loaded1
is run in a second pass, after all, Snappers have been loaded far enough to have their loaded0()
execute. Any initialization or conversion that depends on groups of Snappers should occur here. loaded1()
also must have it's super()
executed.
loadFailed
public loadFailedResult loadFailed(ObjectFormatter formatter, LoadFailure failure) { // ... }
loadFailed
is used to react to fields that do not load. Based on the specific LoadFailure
, recovery code is called, and a loadFailedResult
(.ignore, .survive, or .fail, at the time of writing) is returned.
Generally, you do if (failure as TYPE) tests to upcast to RemovedFieldLoadFailure
, ChangedFieldTypeLoadFailure
, UninitializedFieldLoadFailure
, UndefFieldTypeLoadFailure
, etc., then switch on failure.fieldName
.
Comments
0 comments
Please sign in to leave a comment.