È possibile ottenere questo errore se si sottoclasse una vista personalizzata in modo errato.
Si supponga di essere in sottoclasse BottomNavigationView
e si desidera aggiungere lo stato salvato al superstato in onSaveInstanceState()
.
Un'implementazione non corretta della boilerplate Parcelable (copiato da un'altra classe o un modello) sarebbe simile a questa:
static class State extends BaseSavedState {
Bundle stateBundle;
//incorrect as super state uses ClassLoaderCreator
public static final Creator<State> CREATOR = new Creator<State>() {
public State createFromParcel(Parcel in) {
return new State(in);
}
public State[] newArray(int size) {
return new State[size];
}
};
State(Parcel source) {
super(source);
this.stateBundle = source.readBundle(getClass().getClassLoader());
}
State(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeBundle(stateBundle);
}
}
Questo non avrebbe funzionato come il superstato da BottomNavigationView
richiede un classloader. Invece si dovrebbe controllare attentamente la classe SavedState
da BottomNavigationView
e utilizzare il corretto ClassLoaderCreator
piuttosto che Creator
:
static class State extends AbsSavedState {
Bundle stateBundle;
public static final Creator<State> CREATOR = new ClassLoaderCreator<State>() {
public State createFromParcel(Parcel in, ClassLoader classLoader) {
return new State(in, classLoader);
}
@Override
public State createFromParcel(Parcel source) {
return new State(source, null);
}
public State[] newArray(int size) {
return new State[size];
}
};
State(Parcel source, ClassLoader classLoader) {
super(source, classLoader);
this.stateBundle = source.readBundle(classLoader);
}
State(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeBundle(stateBundle);
}
}
Nota che l'estensione android.support.v4.view.AbsSavedState
può essere una scelta migliore di BaseSavedState
o android.view.AbsSavedState
in quanto vi permetterà di passare una classe loader per la superclasse:
SavedState(Parcel source, ClassLoader classLoader) {
super(source, classLoader); //available in android.support.v4.view.AbsSavedState
this.stateBundle = source.readBundle(classLoader);
}
fonte
2018-01-23 23:19:43
Ho ricevuto questo errore in un contesto diverso - chiamando 'bundle.keySet()' su un pacchetto che conteneva un Parcelable. Durante l'esecuzione di una singola classe di test rispetto al codice in questione, è passata, ma l'esecuzione dell'intera suite di test ha portato a 'BadParcelableException'. La "correzione" era di fare 'bundle.setClassloader (MyClass.class.getClassLoader())' prima di 'bundle.keySet()'. –