当前位置: 首页 > 知识库问答 >
问题:

当方向改变时,用标签重新加载活动时,片段会被初始化两次

吕宇定
2023-03-14

当我改变设备的方向时,我在重新加载带有选项卡和片段的活动时遇到问题。

我有一个活动,其中有3个标签在行动栏。每个选项卡在主视图中的frameLayout中加载不同的片段。如果我不改变设备的方向,一切都很好。但是当我这样做的时候,Android尝试初始化当前选择的片段两次,这会产生以下错误:

E/AndroidRuntime(2022): Caused by: android.view.InflateException: Binary XML file line #39: Error inflating class fragment

以下是产生错误的步骤顺序:

  1. 我加载活动,选择标签NR2。并更改设备的方向。
  2. Android会破坏标签NR2加载的活动和片段的实例(从现在开始,'Fragment2')。然后继续创建活动和片段的新实例。
  3. activity.oncreate()中,我将第一个选项卡添加到操作栏。当我这样做时,这个选项卡会自动被选中。它可能代表着将来的一个问题,但我现在不介意那个。调用ontabselect,并创建和加载第一个片段的新实例(请参见下面的代码)。
  4. 我添加所有其他选项卡而不触发任何事件,这很好。
  5. 我调用actionbar.selecttab(myTab)来选择Tab nr 2。
  6. 第一个选项卡调用
  7. ontabunselected(),第二个选项卡调用ontabselected()。此序列将当前片段替换为片段2的实例(请参见下面的代码)。
  8. 接下来,在片段2实例上调用Fragment.oncreateview(),片段布局得到膨胀。
  9. 问题出在这里。Android再次对片段实例调用oncreate(),然后调用oncreateView(),当我试图(第二次)膨胀布局时,会产生异常。
public class MyActivity extends Activity  implements ActionBar.TabListener {

    private static final String TAG_FRAGMENT_1 = "frag1";
    private static final String TAG_FRAGMENT_2 = "frag2";
    private static final String TAG_FRAGMENT_3 = "frag3";

    Fragment frag1;
    Fragment frag2;
    Fragment frag3;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // my_layout contains a FragmentLayout inside
        setContentView(R.layout.my_layout); 

        // Get a reference to the fragments created automatically by Android
        // when reloading the activity
        FragmentManager fm = getFragmentManager();
        this.frag1 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_1);
        this.frag2 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_2);
        this.frag3 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_3)


        ActionBar actionBar = getActionBar();

        // snip...

        // This triggers onTabSelected for the first tab
        actionBar.addTab(actionBar.newTab()
                .setText("Tab1").setTabListener(this)
                .setTag(MyActivity.TAG_FRAGMENT_1));

        actionBar.addTab(actionBar.newTab()
                .setText("Tab2").setTabListener(this)
                .setTag(MyActivity.TAG_FRAGMENT_2));
        actionBar.addTab(actionBar.newTab()
                .setText("Tab3").setTabListener(this)
                .setTag(MyActivity.TAG_FRAGMENT_3));

        Tab t = null;
        // here I get a reference to the tab that must be selected
        // snip...

        // This triggers onTabUnselected/onTabSelected
        ab.selectTab(t);

    }

    @Override
    protected void onDestroy() {
        // Not sure if this is necessary
        this.frag1 = null;
        this.frag2 = null;
        this.frag3 = null;
        super.onDestroy();
    }

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

        Fragment curFrag = getFragmentInstanceForTag(tab.getTag().toString());
        if (curFrag == null) {
            curFrag = createFragmentInstanceForTag(tab.getTag().toString());
            if(curFrag == null) { 
                // snip... 
                return;
            }
        }
        ft.replace(R.id.fragment_container, curFrag, tab.getTag().toString());
    }

    @Override  
    public void onTabUnselected(Tab tab, FragmentTransaction ft) 
    {  
        Fragment curFrag = getFragmentInstanceForTag(tab.getTag().toString());
        if (curFrag == null) {
            // snip... 
            return;
        }

        ft.remove(curFrag);
    }

    private Fragment getFragmentInstanceForTag(String tag) 
    {
        // Returns this.frag1, this.frag2 or this.frag3
        // depending on which tag was passed as parameter
    }

    private Fragment createFragmentInstanceForTag(String tag) 
    {
        // Returns a new instance of the fragment requested by tag
        // and assigns it to this.frag1, this.frag2 or this.frag3
    }
}

共有1个答案

杨选
2023-03-14

我用下面的代码解决了这个问题。

private void loadFragment(){
     LogUtil.l(TAG,"loadFragment",true);
     fm = getSupportFragmentManager();
     Fragment hf = fm.findFragmentByTag("HOME");
     Fragment sf = fm.findFragmentByTag("SETTING");
     if(hf==null) {
         homeFragment = getHomeFragment();// new HomeFragment();
         settingsFragment = getSettingsFragment();// new Fragment();
         fm.beginTransaction().add(R.id.fm_place, settingsFragment, "SETTING").hide(settingsFragment).commit();
         fm.beginTransaction().add(R.id.fm_place, homeFragment, "HOME").commit();
         activeFragment = homeFragment;
     }else{
         homeFragment = hf;
         settingsFragment = sf;
         activeFragment = sf;
     }
 }

在OnCreate()中启动此方法;

 类似资料:
  • 我目前正试图在android studio中创建一个日历应用程序。该应用包含一个具有不同“视图”的日历,例如月视图、周视图和日视图。 该应用程序使用片段作为页面,每个视图都是一个活动。 这是片段和按钮初始化每个视图的代码 在代码中显示日历月度视图的第一个按钮称为“Calendaractive”正常工作,但当单击显示日历每周视图的第二个按钮时,会导致应用程序崩溃并在logcat中给出以下错误 我不确

  • 我有一个由一个活动和几个片段组成的应用程序,由谷歌重新指挥。其他细节在这里。我想保持一个菜单静止和切换我的碎片在容器在中心。 当我启动该活动时,它会初始化一个变量,如代码所示。 但是,当我在fragment onCreate中使用这个变量()时,活动中的绑定行会因,如下面的logcat所示 下面是完整的logcat,我们可以看到第二个sout丢失了,但在这一点上没有抛出错误。

  • 问题内容: 我目前在 此URL实际上按照以下路由指示加载Module.js类: 这包含在index.js文件中定义的和元素中。 Module类具有和方法。这些设置了记录2的初始详细信息和装入信息。到目前为止一切正常。 现在,我的问题是,在Module.js的孙组件中,我使用以下Redirect重定向到另一个页面,例如第3页: 构造函数或componentWillMount无法运行,因此记录#3无法

  • 我在应用程序中使用Sherlock操作栏。我在菜单中使用了“ifRoom | with text”功能。如果我在纵向模式下测试代码,我只能看到图标,如果我将方向旋转到横向,我仍然只能看到图标。另一方面,如果我使用横向,我可以在纵向和横向上看到文本和图标。这意味着当屏幕旋转时,操作栏不会刷新。我如何修复? 菜单里,我有 我还在清单文件中使用这一行来修复 但它不起作用。我运行我的代码android 2

  • 在我之前提到的活动的自定义回收器视图适配器中,我想在点击我的一个元素时对碎片进行充电,例如: 这是我的片段类: 这个片段还加载了一个google Maps片段,您可以在它的布局中看到: 当我在一个项目中第一次点击时,一切正常,但当我在另一个项目中第二次点击时,我会得到以下错误:

  • 我有一个,当用户浏览应用程序时,我将当前片段替换为用户选择的片段,并添加将交易添加到背包。一切正常,用户可以通过按下返回按钮返回到以前的片段。 当设备方向改变时会出现问题:假设用户看到的第一个片段是A,然后他导航到B,并从B导航到C。在横向模式下,可以更好地欣赏C中的内容,并且C有一个特殊的横向布局,因此用户旋转设备。我希望用户使用C语言进行新的定位。相反,用户看到的是景观。现在他需要再次从A导航