IllegalArgumentException: No view found for id for fragment when fast switching ActionBar Tabs

烂漫一生 提交于 2019-11-29 06:38:40

Okay, found a way around this:

Put the references to the fragments in the layout files, and surrounded the setContentView call in onTabSelected in a try/catch block.

The exception handling took care of it!

Budius

I know it's a slightly old question but I was having the same and find a different work around.

The method itself is described here Avoid recreating same view when perform tab switching

but on the context of this specific crash, doing Show/Hide instead of add/replace avoids multiple fast calls to onCreateView on the fragment.

My final code ended up something like this:

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
if (fragments[tab.getPosition()] == null) {
     switch(tag.getPosition()){
        case 0: fragments[tab.getPosition()] = new // fragment for this position
        break;
        // repeat for all the tabs, for each `case`
     }
     fragmentTransaction.add(R.id.container, fragments[tab.getPosition()]);
}else{
     fragmentTransaction.show(fragments[tab.getPosition()]);
}
 }

@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
if (fragments[tab.getPosition()] != null)
    fragmentTransaction.hide(fragments[tab.getPosition()]);
}

Seeing a similar case in a Google Play crash report.

java.lang.IllegalStateException:
    Fragment not added: MessageDisplayFragment{406e28f0 #2 id=0x7f0b0020}
at android.app.BackStackRecord.hide(BackStackRecord.java:397)
at org.kman.AquaMail.ui.AccountListActivity$UIMediator_API11_TwoPane.
    closeMessageDisplay(AccountListActivity.java:2585)

Relevant code:

AbsMessageFragment fragDisplay = (AbsMessageFragment)
    mFM.findFragmentById(R.id.fragment_id_message_display);

if (fragDisplay != null) {
    FragmentTransaction ft = mFM.beginTransaction();
    ft.setTransition(FragmentTransaction.TRANSIT_NONE);
    ft.show(some other fragment);
    ft.hide(fragDisplay);

^^ This is where it crashes

The fragment is definitely there (it was returned by findFragmentById), but calling hide() blew up with the "IllegalStateException: Fragment not added"

Not added? How's it not added if findFragmentById was able to find it?

All FragmentManager calls are being made from the UI thread.

The fragment being removed (fragDisplay) was added earlier and I'm sure that its FragmentTransaction was commited.

Fixed it by looping through my fragments, removing any of them which have been added and then adding the new one. Also check first that you're not trying to replace it with null or an existing fragment.

Edit: looks like it was just

getChildFragmentManager().executePendingTransactions();

that stopped it from crashing

private void replaceCurrentTabFragment(TabFragment tabFragment){

    if (tabFragment == null){ return; }

    if (tabFragment == getActiveTabFragment()){ return; }

    FragmentTransaction ft = getChildFragmentManager().beginTransaction();

    for (TabFragment fragment : mTabButtons.values()){
        if (((Fragment)fragment).isAdded()){
            ft.remove((Fragment)fragment);
        }
    }

    ft.add(R.id.fragment_frameLayout, (Fragment) tabFragment);
    ft.commit();
    getChildFragmentManager().executePendingTransactions();

}

private TabFragment getActiveTabFragment(){
    return (TabFragment) getChildFragmentManager().findFragmentById(R.id.fragment_frameLayout);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!