This is a migrated thread and some comments may be shown as answers.

Crash in RadDataFormInstanceState on onSaveInstanceState

6 Answers 31 Views
DataForm
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Sacha
Top achievements
Rank 1
Sacha asked on 08 Jun 2016, 10:44 PM

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

Sort by
0
Victor
Telerik team
answered on 13 Jun 2016, 02:03 PM
Hello Sacha,

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
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Sacha
Top achievements
Rank 1
answered on 13 Jun 2016, 02:08 PM

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);
}

0
Victor
Telerik team
answered on 13 Jun 2016, 02:58 PM
Ah yes, my bad.
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
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Sacha
Top achievements
Rank 1
answered on 13 Jun 2016, 03:06 PM

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);
}

0
Victor
Telerik team
answered on 13 Jun 2016, 03:55 PM
Hi Sacha,

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
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Sacha
Top achievements
Rank 1
answered on 23 Jun 2016, 12:54 PM

Cool thanks. Another workaround is to set this in the RadDataForm layout xml:

android:saveEnabled="false"

Tags
DataForm
Asked by
Sacha
Top achievements
Rank 1
Answers by
Victor
Telerik team
Sacha
Top achievements
Rank 1
Share this question
or