Обновление моего фрагмента не работает, как я думал

У меня есть этот хороший метод в моем 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: ОШИБКА/AndroidRuntime(2048): Причина: java.lang.IllegalStateException: невозможно выполнить это действие после onSaveInstanceState

Итак, я предполагаю, что то, что я пытаюсь сделать, не так резко и сухо, как это звучит, для меня это не имеет смысла, поскольку я могу делать это onListItemClicked весь день, и фрагмент постоянно очень хорошо отображает детали недавно щелкнутого клиента. .

Я даже пробовал это в своем onActivityResult:

//simulate a click event really fast to refresh the client details
showClientDetails(0);
showClientDetails(mCurrentSelectedItemIndex);

это ничего не делает, я пытаюсь вызвать что-то из onActivityResult, которое не является потоком пользовательского интерфейса или что-то еще?

У меня есть это и в моем коде ListFragment.

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

Это то, на что жалуется ошибка?


person Codejoy    schedule 08.07.2011    source источник


Ответы (3)


Другое действие FragmentActivity выполняет задачу, которая требует от Fragment сохранения своего состояния посредством вызова onSaveInstanceState в рамках подготовки к реконструкции нового экземпляра. Я видел это, например, когда запускал действие из фрагмента, который заполнял весь экран, поскольку это приводило к отсоединению представления от фрагмента, необходимости сохранения состояния и т. д.

Вы в принципе не можете вызывать commit между onSaveInstanceState и новым экземпляром воссоздаваемого фрагмента. См. раздел фиксация.

Что касается решения, то либо подумайте еще раз, чтобы попытаться избежать вызова commit, когда он есть, либо, альтернативно, вызовите commitAllowingStateLoss, если вы считаете, что пользовательский интерфейс может неожиданно измениться для пользователя.

person PJL    schedule 11.07.2011
comment
Спасибо за ответ. Отображаемый клиент обновляется из окна редактирования клиентов, поэтому я не думаю, что это неожиданно, и я думаю, что commitAllowingStateLoss в порядке. - person Codejoy; 12.07.2011
comment
Я использовал commitAllowingStateLoss, но отображал диалоговое окно предупреждения при изменении ориентации. - person Manikandan K; 23.10.2018

Я думаю, что ответ заключается в том, чтобы не выполнять никаких фрагментных транзакций в onActivityResult. Я считаю, что происходит то, что когда onActivityResult вызывается, активность, в которой она находится, еще не возобновилась и не перезапустила свои фрагменты. Используйте обработчик, чтобы отправить вызов функции в действие.

handler.post(new Runnable() {
    @Override
    public void run() {
        showClientDetails(mCurrentSelectedItemIndex);
    }
});
person Shinyosan    schedule 01.11.2011
comment
Хотите знать, будет ли это работать, если ваше приложение находится в фоновом режиме и остается в фоновом режиме, когда вызывается onActivityResult? - person PJL; 10.07.2012

вы можете сделать другую вещь, которая не очень хороша, но она работает.

  • закончить (вашу деятельность)
  • сделать намерение того же класса:

Намерение mIntent = новое намерение (getApplicationContext(), YouClass.class);

startActivity(mIntent);

person douarbou    schedule 30.11.2012