抛出:IllegalArgumentException:没有查看发现ID为片段时快速切换动作条的标签抛出、片段、动作、快速

2023-09-13 01:05:28 作者:西江月

我正在开发针对平板电脑的Andr​​oid应用程序和不可以使用兼容性库。

I am developing an Android app for tablets and not using the compatibility library.

只有一个活动,并使用具有3个标签的动作条。 在TabListener我使用的setContentView加载特定于该标签的布局,然后添加相关片段到其的帧。 这的几乎的工作原理完全一样我想,当你在标签之间切换,除了速度不够快,应用程序将崩溃。

There is just one Activity and it uses the ActionBar with 3 tabs. In the TabListener I use setContentView to load the layout specific to that tab, and then add the relevant fragments to their frames. This almost works exactly like I want, except when you switch between the tabs fast enough the app will crash.

我使用的是三星Galaxy Tab作为我的调试器和切换标签是真快。在一个正常的速度,我可以挖掘来回它们之间的页面即时加载。问题是,当我在标签之间切换过度。

I am using a Samsung Galaxy Tab as my debugging device and switching tabs is really fast. At a normal pace I can tap back and forth between them and the pages are loaded instantly. The problem is when I hyper switch between the tabs.

起初,我得到了一个

IllegalStateException: Fragment not added

看这里: http://$c$c.google.com/p/android/issues/detail?id=17029 下面以使用onTabUnselected try / catch块的建议,我做了应用程序多了几分稳健,但导致手头的问题:

as seen here: http://code.google.com/p/android/issues/detail?id=17029 Following the suggestion to use try/catch blocks in onTabUnselected, I made the app a little more robust, but that lead to the issue at hand:

IllegalArgumentException: No view found for id 0x... for fragment ...

我还没有发现其他人有同样的问题在网络上任何其他情况下,所以我很担心,我可能会做的不是支持的东西。 再次,我所要做的是使用3种不同的布局,在一个活动 - 当你点击一个选项卡,监听器将调用的setContentView改变布局,然后添加片段。它精美的作品,除非你开始积极地标签之间切换。

I have not found any other case on the web of anyone else having the same issue, so I am concerned that I may be doing something that's not supported. Again, what I am trying to do is use 3 different layouts in one Activity - when you click on a tab, the listener will call setContentView to change the layout, and then add the fragments. It works beautifully unless you start aggressively switching between tabs.

我有这个的想法来自:http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html 和代替TabListener保持参考一个片段,我对这些阵列。另外,我不使用安装/拆卸,因为这些刚刚加入API 13

I got the idea for this from: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html and instead of the TabListener keeping a reference to one fragment, I have an array of them. Also, I am not using attach/detach since those were just added in API 13.

我的理论是,要么的setContentView未完成创建的意见,这就是为什么当另一个选项卡,并的setContentView被称为FragmentTransaction不能添加它们,或者将片段添加了一个选项卡,摧毁了另一组的意见。

My theory is that either setContentView hasn't finished creating the views, and that's why FragmentTransaction can't add them, OR the fragments are being added for one tab when another tab is selected and setContentView is called, destroying the other set of views.

我试图破解的东西,以减缓选项卡切换,但没有取得任何进展。

I tried to hack something in to slow down tab switching but didn't get anywhere.

下面是code我TabListener:

Here is the code for my TabListener:

private class BTabListener<T extends Fragment> implements ActionBar.TabListener{

    private int mLayout;
    private Fragment[] mFrags;
    private TabData mTabData;
    private Activity mAct;
    private boolean mNoNewFrags;


    public BTabListener(Activity act, int layout, TabData td, boolean frags){
        mLayout = layout;
        mTabData = td;
        mAct = act;
        mNoNewFrags = frags;

        mFrags = new Fragment[mTabData.fragTags.length];
        for(int i=0; i<mFrags.length; i++){
            //on an orientation change, this will find the fragments that were recreated by the system
            mFrags[i] = mAct.getFragmentManager().findFragmentByTag(mTabData.fragTags[i]);
        }

    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        //this gets called _after_ unselected
        //note: unselected wont have been called after an orientation change!
        //we also need to watch out because tab 0 always gets selected when adding the tabs

        //set the view for this tab
        mAct.setContentView(mLayout);

        for(int i=0; i<mFrags.length; i++){
            //this will be null when the tab is first selected
            if(mFrags[i]==null ){
                mFrags[i] = Fragment.instantiate(GUITablet.this, mTabData.classes[i].getName());                    
            }

            //if there was an orientation change when we were on this page, the fragment is already added
            if(!mNoNewFrags || mDefaultTab!=tab.getPosition()){
                ft.add(mTabData.containterIDs[i], mFrags[i], mTabData.fragTags[i]);
            }
        }
        mNoNewFrags = false;


    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // this gets called when another tab is selected, before it's onSelected method 

        for(Fragment f : mFrags){
            try{ //extra safety measure
                ft.remove(f);
            }catch(Exception e){
                e.printStackTrace();
                System.out.println("unselect couldnt remove");
            }
        }
    }

}

最后,堆栈跟踪:

And finally, the stack trace:

09-29 01:53:08.200: ERROR/AndroidRuntime(4611): java.lang.IllegalArgumentException: No view found for id 0x7f0b0078 for fragment Fraggle{40ab2230 #2 id=0x7f0b0078 dummy2}
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:729)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:926)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.app.BackStackRecord.run(BackStackRecord.java:578)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1226)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.app.FragmentManagerImpl$1.run(FragmentManager.java:374)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.os.Handler.handleCallback(Handler.java:587)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.os.Handler.dispatchMessage(Handler.java:92)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.os.Looper.loop(Looper.java:132)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at android.app.ActivityThread.main(ActivityThread.java:4028)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at java.lang.reflect.Method.invokeNative(Native Method)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at java.lang.reflect.Method.invoke(Method.java:491)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611):     at dalvik.system.NativeStart.main(Native Method)

谢谢!

推荐答案

好了,找到了解决此方式:

Okay, found a way around this:

把引用片段在布局文件,并包围onTabSelected中的setContentView调用在try / catch块。

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

异常处理照顾它!