android-3.0-honeycomb - 非法参数异常 : No view found for id for fragment when fast switching ActionBar Tabs

标签 android-3.0-honeycomb android-fragments android

我正在开发适用于平板电脑的 Android 应用程序并且使用兼容性库。

只有一个 Activity,它使用带有 3 个选项卡的 ActionBar。 在 TabListener 中,我使用 setContentView 加载特定于该选项卡的布局,然后将相关 fragment 添加到它们的框架中。 这几乎完全按照我想要的方式工作,除非您在选项卡之间切换的速度足够快时应用程序会崩溃。

我使用 Samsung Galaxy Tab 作为我的调试设备,切换标签非常快。以正常的速度,我可以在它们之间来回点击,页面会立即加载。问题是当我在选项卡之间进行 super 切换时。

一开始我得到了一个

IllegalStateException: Fragment not added

如下所示: http://code.google.com/p/android/issues/detail?id=17029 按照在 onTabUnselected 中使用 try/catch block 的建议,我使应用程序更加健壮,但这导致了手头的问题:

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

我没有在网络上发现任何其他人遇到同样问题的其他案例,所以我担心我可能会做一些不受支持的事情。 同样,我想做的是在一个 Activity 中使用 3 种不同的布局 - 当您单击一个选项卡时,监听器将调用 setContentView 来更改布局,然后添加 fragment 。除非您开始积极地在选项卡之间切换,否则它会很好地工作。

我的想法来自:http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html 而不是 TabListener 保留对一个 fragment 的引用,我有一个数组。另外,我没有使用附加/分离,因为它们刚刚添加到 API 13 中。

我的理论是 setContentView 尚未完成 View 的创建,这就是 FragmentTransaction 无法添加它们的原因,或者当另一个选项卡被选中并调用 setContentView 时,正在为一个选项卡添加 fragment ,从而破坏另一组意见。

我试图破解一些东西来减慢标签切换的速度,但没有成功。

这是我的 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");
            }
        }
    }

}

最后,堆栈跟踪:

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)

谢谢!!

最佳答案

好的,找到解决方法:

将对 fragment 的引用放在布局文件中,并将 onTabSelected 中的 setContentView 调用包围在 try/catch block 中。

异常处理解决了它!

关于android-3.0-honeycomb - 非法参数异常 : No view found for id for fragment when fast switching ActionBar Tabs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7589032/

相关文章:

android - 当Fragment处于Resume状态时,如何将TEXT设置为Fragment的TextView?

java - Android:抽屉导航布局动态更改图标

android - 当关闭对话框 fragment 时,无法在 onSaveInstanceState 之后执行此操作

java - 如何使用 RecyclerView 创建两列?

Android:向 ListView App Widget 添加多个 View

java - Android WebView 302 重定向 - 蜂窝

android - Spinner 从 SQLite 数据库填充空选择

java - 如何添加工具栏?

android - 编译 Android RenderScript 示例时出错

android - 如何在android 3.0中忽略 "Recent Activity Button"的按钮点击