I have a custom view that performs some network operations. From that operation result the view builds UI.
The view contains a list of cards that are fetched via internet. This view is used in multiple places. Lets say one of them is my fragment.
Here's what I do inside of fragment:
class MyFragment extends Fragment {
// same as findViewById
@BindView(R.id.card_list) CardHelper cardHelper;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// init my element with some data before it initializes
cardHelper.init(data);
}
}
Here's how my custom view looks like:
public class CardHelper extends ListView {
// some info that is built from internet data
private List<HashMap<String, String>> cardElements = new ArrayList<>();
public void init(Data data) {
// does async network and then build a view based on results
// Network operations could depend on data param
}
}
OK, now when user switches from my app to another one, my Fragment could be destroyed. And I wanna saved the state of my custom view. Thus my view doesn't need to get information from internet again. So I append my CardHelper
with the following data (based on this answer):
public class CardHelper extends ListView {
// some info that is built from internet data
private List<HashMap<String, String>> cardElements = new ArrayList<>();
public void init(Data data) {
// does async network and then build a view based on results
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.cardElements = this.cardElements;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if(state instanceof SavedState) {
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
this.cardElements = ss.cardElements;
} else {
super.onRestoreInstanceState(state);
}
}
private static class SavedState extends BaseSavedState {
private List<HashMap<String, String>> cardElements = new ArrayList<>();
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.cardElements = new ArrayList<>();
in.readList(this.cardElements, null);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeList(this.cardElements);
}
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
For the sake of argument, I wanna save the view's data from this view itself. So fragments/activities or w/e use it wouldn't need to know anything how it works inside. And if I use it from multiple places I wouldn't need to duplicate code that stores\restores this view.
Ok, to the problem now:
When CardHelper is created the very first time I perform init
to initialize the view manually with some data
. When my fragment gets destroyed and app goes to background and then gets restored, methods are executed in the following priority:
- SavedState: private SavedState(Parcel in) {
- SavedState: public void writeToParcel(Parcel out, int flags) {
- CardHelper: public void init(Data data) {
- CardHelper: public void onRestoreInstanceState(Parcelable state) {
As you see onRestoreInstanceState
executed only after onActivityCreated
. But I need to know if I should perform network operation in init
method before that. So I want to onRestoreInstanceState
be executed first and only then init
. But there're no method in fragments LifeCycle that could be done after this.
How to I reformat my code that I can call some operation within my fragment after onRestoreInstanceState
on CardHelper
gets called? One more thing that onRestoreInstanceState
wouldn't be called for the first time when CardHelper
is created. But I need to initialize my CardHelper in this case as well.