Reputation: 9709
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:
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.
Upvotes: 0
Views: 268
Reputation: 62189
The easy fix should be posting the init()
step after cardHelper
has been laid out, therefore onRestoreInstanceState
has already been called. To do that you just have to perform init()
in post(...)
:
cardHelper.post(new Runnable() {
public void run() {
cardHelper.init();
}
});
Haven't tested it, I assume it will work.
Upvotes: 1