I have this nice method in my ListFragment I call to fill out the details of my other fragment:
private void showClientDetails(int pos) {
myCursor.moveToPosition(pos);
int clientId = myCursor.getInt(0);
if(mIsTablet) {
// Set the list item as checked
getListView().setItemChecked(mCurrentSelectedItemIndex, true);
// Get the fragment instance
ClientDetails details = (ClientDetails) getFragmentManager().findFragmentById(R.id.client_details);
// Is the current visible recipe the same as the clicked? If so, there is no need to update
if (details == null || details.getClientIndex() != mCurrentSelectedItemIndex) {
// Make new fragment instance to show the recipe
details = ClientDetails.newInstance(mCurrentSelectedItemIndex, clientId, mIsTablet);
// Replace the old fragment with the new one
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.client_details, details);
// Use a fade animation. This makes it clear that this is not a new "layer"
// above the current, but a replacement
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
}
}
It is called when the user clicks on a client in the ListFragment view:
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCurrentSelectedItemIndex = position;
showClientDetails(position);
}
This works great, but then another FragmentActivity can change the data that this displays so I thought this would work:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//update the client list incase a new one is added or the name changes
if(requestCode==1899)
{
myCursor.requery();
theClients.notifyDataSetChanged();
showClientDetails(mCurrentSelectedItemIndex); //now if client was edited update their details in the details fragment
}
}
Now I know the line:
if (details == null || details.getClientIndex() != mCurrentSelectedItemIndex) {
Prevents the block of code being reached when its called in my onActivityResult. So if I remove that if
statement, then things freak out and the ft.commit() has a hissy fit and gives me the error:
`07-08 16:53:31.783: ERROR/AndroidRuntime(2048): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
So I guess what I am trying to do isn't as cut and dry as it sounds, it makes no sense to me since I can do that onListItemClicked all day and the fragment displays the details of the newly clicked client constantly very well...
I even tried this in my onActivityResult
:
//simulate a click event really fast to refresh the client details
showClientDetails(0);
showClientDetails(mCurrentSelectedItemIndex);
that does nothing, is it im trying to call something from the onActivityResult which isn't a Ui thread or what not?
I do have this in my code of the ListFragment as well
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentListIndex", mCurrentSelectedItemIndex);
}
Is this what the error is complaining about?
I think the answer is to not do any fragment transactions in the onActivityResult. I believe what happens is that when the onActivityResult is called the activity it is in hasn't yet resumed and restarted its fragments. Use a handler to post back the function call to the activity.
you can do an other thing which no very good but it works.
The other
FragmentActivity
's action is performing a task which requires theFragment
to save its state via a call toonSaveInstanceState
in preparation for a new instance being reconstructed. I've seen this for example when I was firing off an activity from a fragment which filled the entire screen as this resulted in the view being detached from the fragment, state needing to be saved etc.You basically cannot call
commit
betweenonSaveInstanceState
and the new instance of the fragment being recreated. See commit.As for the solution, then either re-think to try and avoid the
commit
being called when it is or alternatively callcommitAllowingStateLoss
if you think it's OK for the UI to change unexpectedly on the user.