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"