Hi,
I have noticed that if you annotate a field with skip = true, then when onSaveInstanceState is called, there is a crash. The problem is this:
If skip = true, then the property is not added to the list of properties in DataFormEntityAdapter.generateProperties
if(!property.getSkip()) { this.properties.add(property);}But, in RadDataFormInstanceState constructor, it iterates over all properties (whether they have been skipped or not), and tries to find an editor. This will fail and dataForm.getExistingEditorForProperty(property.name()) will return null, so when getEditorView is called on the null return value, it crashes.
public RadDataFormInstanceState(Parcelable superState, RadDataForm dataForm) { super(superState); this.editorIds = new HashMap(); Iterator i$ = dataForm.getEntity().properties().iterator(); while(i$.hasNext()) { EntityProperty property = (EntityProperty)i$.next(); this.editorIds.put(property.name(), Integer.valueOf(dataForm.getExistingEditorForProperty(property.name()).getEditorView().getId())); }}It would be great if you could provide a fix, but in the meantime it would be totally awesome if you could suggest a workaround. Basically, I don't want all the fields in an annotated class to be shown in the DataForm - I want to hide some of them.
Many thanks
Sacha
6 Answers, 1 is accepted
Thanks for reporting this. I have fixed it in our development branch.
The fix will be available in our next release.
Currently you can work around it simply by inheriting from RadDataForm and overriding the onSaveInstanceState() and onRestoreInstanceState(). Also the RadDataFormInstanceState class is public so you can override its methods as well.
Regards,
Victor
Telerik
Thanks Victor. I looked at inheriting from RadDataForm and overriding onSaveInstanceState, but the problem is that RadDataForm calls super.onSaveInstanceState. So in my inherited data form, I would need to do something like the code below.
But I can't call super.super in Java.
Any suggestions?
protected Parcelable onSaveInstanceState() { return new RadDataFormInstanceStateWithTheFix(super.super.onSaveInstanceState(), this);}In this case you will have to completely overwrite the RadDataFormInstanceState class. For example:
@Override protected Parcelable onSaveInstanceState() { return new CustomRadDataFormInstanceState(super.onSaveInstanceState(), this); } @Override protected void onRestoreInstanceState(Parcelable state) { CustomRadDataFormInstanceState dataFormState = (CustomRadDataFormInstanceState)state; for(EntityProperty property : this.entity.properties()) { if(property.getSkip()) { continue; } getExistingEditorForProperty(property.name()).getEditorView().setId(dataFormState.editorIds.get(property.name())); } super.onRestoreInstanceState(dataFormState.getSuperState()); }And the state class itself:
public class CustomRadDataFormInstanceState extends View.BaseSavedState { public static final Parcelable.Creator<CustomRadDataFormInstanceState> CREATOR = new Parcelable.Creator<CustomRadDataFormInstanceState>() { @Override public CustomRadDataFormInstanceState createFromParcel(Parcel source) { return new CustomRadDataFormInstanceState(source); } @Override public CustomRadDataFormInstanceState[] newArray(int size) { return new CustomRadDataFormInstanceState[size]; } }; public HashMap<String, Integer> editorIds = new HashMap<>(); public CustomRadDataFormInstanceState(Parcelable superState) { this(superState, null); } public CustomRadDataFormInstanceState(Parcelable superState, RadDataForm dataForm) { super(superState); for(EntityProperty property : dataForm.getEntity().properties()) { if(property.getSkip()) { continue; } editorIds.put(property.name(), dataForm.getExistingEditorForProperty(property.name()).getEditorView().getId()); } } public CustomRadDataFormInstanceState(Parcel superState) { super(superState); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeMap(editorIds); } }Please write again if you need further assistance.
Regards,
Victor
Telerik
Hi Victor,
Will that work? Because when the following call is made, it will call super.onSaveInstanceState, which will then call RadDataFormInstanceState, not CustomRadDataFormInstanceState:
protected Parcelable onSaveInstanceState() { return new CustomRadDataFormInstanceState(super.onSaveInstanceState(), this);}Yes you are correct. There appears to be no way to avoid the base instance state object.
I suggest modifying the controls source in this case. As a customer you should have access to source of the controls. You can modify it with this change and create your own custom build that you can use in your app.
If you are reluctant to modify the source I can send you a private development build with the fix. This second option however may expose your app to untested features.
Regards,
Victor
Telerik
Cool thanks. Another workaround is to set this in the RadDataForm layout xml:
android:saveEnabled="false"