Refreshing my fragment not working like I thought

2020-06-25 05:51发布

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?

3条回答
冷血范
2楼-- · 2020-06-25 06:07

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.

handler.post(new Runnable() {
    @Override
    public void run() {
        showClientDetails(mCurrentSelectedItemIndex);
    }
});
查看更多
smile是对你的礼貌
3楼-- · 2020-06-25 06:07

you can do an other thing which no very good but it works.

  • finish (you activity)
  • do an intent of that same class by :

Intent mIntent = new Intent(getApplicationContext(), YouClass.class);

startActivity(mIntent);

查看更多
兄弟一词,经得起流年.
4楼-- · 2020-06-25 06:12

The other FragmentActivity's action is performing a task which requires the Fragment to save its state via a call to onSaveInstanceState 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 between onSaveInstanceState 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 call commitAllowingStateLoss if you think it's OK for the UI to change unexpectedly on the user.

查看更多
登录 后发表回答