刷新我的片段不像我想的那样工作

时间:2011-07-08 17:37:09

标签: android android-fragments

我在ListFragment中有这个很好的方法我打电话来填写我的其他片段的细节:

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();
                }
        }
}

当用户在ListFragment视图中单击客户端时调用它:

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
       mCurrentSelectedItemIndex = position;    
           showClientDetails(position);
}

这很好用,但是另一个FragmentActivity可以更改显示的数据,所以我觉得这样可行:

@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
    }
}

现在我知道了这一行:

if (details == null || details.getClientIndex() != mCurrentSelectedItemIndex) {

防止在我的onActivityResult中调用代码块。所以如果我删除那个if语句,那么事情会变得很糟糕,ft.commit()有一个非常合适的错误并给我错误:

`07-08 16:53:31.783:ERROR / AndroidRuntime(2048):引起:java.lang.IllegalStateException:onSaveInstanceState之后无法执行此操作

所以我想我想要做的事情并不像听起来那样干涩和干燥,因为我可以整天在onListItemClicked上做这件事而且片段显示新点击的客户端的详细信息良好...

我甚至在我的onActivityResult

中尝试过此操作
//simulate a click event really fast to refresh the client details
showClientDetails(0);
showClientDetails(mCurrentSelectedItemIndex);

什么都不做,是我试图从onActivityResult中调用一些不是Ui线程的东西或什么不是?

我在ListFragment的代码中也有这个

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
outState.putInt("currentListIndex", mCurrentSelectedItemIndex);
}

这是错误所抱怨的吗?

3 个答案:

答案 0 :(得分:22)

其他FragmentActivity的操作正在执行一项任务,该任务要求Fragment通过调用onSaveInstanceState来保存其状态,以准备重建新实例。我已经看到了这个例子,当我从一个填满整个屏幕的片段中触发一个活动,因为这导致视图与片段分离,状态需要保存等。

您基本上无法在commit和正在重新创建的片段的新实例之间调用onSaveInstanceState。请参阅commit

至于解决方案,然后重新考虑尝试避免commit被调用,或者如果您认为UI可以在用户上意外更改则调用commitAllowingStateLoss

答案 1 :(得分:19)

我认为答案是不在onActivityResult中执行任何片段事务。我相信所发生的事情是,当onActivityResult被调用时,它所处的活动尚未恢复并重新启动其片段。 使用处理程序将函数调用回发给活动。

handler.post(new Runnable() {
    @Override
    public void run() {
        showClientDetails(mCurrentSelectedItemIndex);
    }
});

答案 2 :(得分:0)

你可以做一件不太好的事情,但它有效。

  • 完成(你的活动)
  • 通过以下方式表达同一类的意图:
  

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

     

startActivity(mIntent);