屏幕旋转后,findFragmentById()返回一个片段,即使布局中没有这样的ID

时间:2013-10-23 06:51:18

标签: android android-layout android-fragments

我有两个方向的布局 - 一个风景和一个肖像。

/layout-land/main.xml 有两个片段:

  • <fragment android:id="@+id/fragment1" .. />
  • <fragment android:id="@+id/fragment2" .. />

/layout/main.xml 只有一个片段:

  • <fragment android:id="@+id/fragment1" .. />

以下是 MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    firstFragment = (FirstFragment) getFragmentManager().findFragmentById(R.id.fragment1);
    secondFragment = (SecondFragment) getFragmentManager().findFragmentById(R.id.fragment2);
}

接下来,我在横向模式下启动MainActivity.java。在这种情况下,

  • firstFragmentsecondFragment都指的是布局中的片段 layout-land/main.xml

然后我将屏幕旋转到纵向模式,并应加载布局文件layout/main.xml。在这种情况下,

  • firstFragment指的是R.id.fragment1
  • secondFragment引用一个不存在的片段。访问其中的任何元素会抛出NullPointerException。 (更确切地说,secondFragment null

当布局中没有定义片段时,如何初始化secondFragment


修改:在http://developer.android.com/training/basics/fragments/creating.html上的Android开发人员文档中找到的原因:

  

当配置更改导致托管这些活动时   要重新启动的片段,其新实例可能会使用不同的布局   不包含与先前布局相同的片段。在这   case仍然会实例化所有以前的片段   在新实例中运行。但是,任何不再是   与视图层次结构中的标记关联不会   他们创建了内容视图,并将从isInLayout()返回false。   (此处的代码还显示了如何确定是否放置了片段   在容器中不再在具有该容器的布局中运行   并避免在这种情况下创建其视图层次结构。)

3 个答案:

答案 0 :(得分:3)

您可以查看如下: 我假设您通过findFragmentById

获得的片段具有Fragment1类
Fragment1 frg1 =getFragmentManager().findFragmentById(R.id.FrgDetalleEvento);
boolean hayDetalle = ( frg1!= null && frg1.isInLayout());

它解决了我的同样问题,希望对你们每个人都有帮助

答案 1 :(得分:2)

也许已经太晚了,但是我把它留给了这个问题的未来程序员,我遇到了类似的问题并以这种方式解决了。

  

逻辑:检查屏幕方向,然后拨打电话   仅当屏幕处于横向模式时才findViewById(R.id.fragment2)。   否则启动另一个屏幕的新意图

非工作代码;

@Override
public void onEventoSeleccionado(Evento e) {

    boolean hayDetalle = (getFragmentManager().findFragmentById(R.id.FrgDetalleEvento) != null);

            if(hayDetalle) {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm",Locale.ENGLISH);
                Log.i("EOLog", "Hay Detalle");
                ((DetalleEventoFragment)getFragmentManager().findFragmentById(R.id.FrgDetalleEvento)).mostrarDetalle(Long.toString(e.getId()),formatter.format(e.getFecha()));
            }
            else {
                Log.i("EOLog", "No hay detalle");           
                Intent i = new Intent(this,DetalleEventoActivity.class);                                        
                Bundle b = new Bundle();
                b.putLong("IDEV", e.getId());           
                b.putLong("FECHA", e.getFecha());           
                i.putExtras(b);
                startActivity(i);
            }

}

工作代码:

@Override
public void onEventoSeleccionado(Evento e) {

      int orientation = getResources().getConfiguration().orientation;

            if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm",Locale.ENGLISH);
                Log.i("EOLog", "Hay Detalle");
                ((DetalleEventoFragment)getFragmentManager().findFragmentById(R.id.FrgDetalleEvento)).mostrarDetalle(Long.toString(e.getId()),formatter.format(e.getFecha()));
            }
            else if(orientation == Configuration.ORIENTATION_PORTRAIT) {
                Log.i("EOLog", "No hay detalle");           
                Intent i = new Intent(this,DetalleEventoActivity.class);                                        
                Bundle b = new Bundle();
                b.putLong("IDEV", e.getId());           
                b.putLong("FECHA", e.getFecha());           
                i.putExtras(b);
                startActivity(i);
            }else
            {
                Log.i("EOLog", "Dispositivo erroneo");
            }

}

我希望这很有用

答案 2 :(得分:0)

请交叉检查您的活动类的setContentView()。

我认为应该是setContentView(R.layout.main);