Android onCreate()和onCreateView()调用的内容远远超过所需(片段)

Android onCreate()和onCreateView()调用的内容远远超过所需(片段),android,Android,有人能解释一下为什么onCreate()和onCreateView()被调用了这么多次,每次方向改变都会增加调用次数吗 这是一个非常简单的应用程序,它由一个活动和两个片段组成。第二个片段动态加载。如果在main.xml中定义这两个片段,就不会有这样的行为 下面是main.xml: 右。类别: public class Right extends Fragment { @Override public void onCreate(Bundle savedInstanceStat

有人能解释一下为什么
onCreate()
onCreateView()
被调用了这么多次,每次方向改变都会增加调用次数吗

这是一个非常简单的应用程序,它由一个
活动
和两个
片段组成。第二个
片段
动态加载。如果在
main.xml
中定义这两个
片段
,就不会有这样的行为

下面是
main.xml

右。类别:

public class Right extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("Right", "onCreate()");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.i("Right", "onCreateView()");
        return inflater.inflate(R.layout.right, container, false);
    }
}
主要类别:

public class Main extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Fragment fg = new Right();
        getFragmentManager().beginTransaction().add(R.id.right_frag, fg)
            .commit();
        Log.i("Main", "onCreate()");
    }
}
多次方向更改后记录:

08-28 21:47:38.220: INFO/Main(1099): onCreate()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreate()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:41.110: INFO/ActivityManager(142): Config changed: {1.0 0mcc0mnc en_US sw800dp w1280dp h752dp xlrg land finger -keyb/v/h -nav/h s.162}
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.170: INFO/Left(1099): onCreate()
08-28 21:47:41.170: INFO/Left(1099): onCreateView()
08-28 21:47:41.170: INFO/Main(1099): onCreate()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.190: INFO/Right(1099): onCreate()
08-28 21:47:41.190: INFO/Right(1099): onCreateView()
08-28 21:47:45.070: INFO/ActivityManager(142): Config changed: {1.0 0mcc0mnc en_US sw800dp w800dp h1232dp xlrg port finger -keyb/v/h -nav/h s.163}
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.130: INFO/Left(1099): onCreate()
08-28 21:47:45.130: INFO/Left(1099): onCreateView()
08-28 21:47:45.130: INFO/Main(1099): onCreate()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreate()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()

我无法指向解释这一点的文档,但解决方案是仅在活动首次加载时创建和添加片段,如下所示:

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

    if (savedInstanceState == null) {
        Fragment fg = new Right();
        getFragmentManager().beginTransaction().add(R.id.right_frag, fg)
            .commit();
    }
    Log.i("Main", "onCreate()");
}

如果不针对不同的方向使用不同的布局,我认为应该在清单中使用
android:configChanges=“orientation”

方向更改会导致系统经历保存实例状态、暂停、停止、销毁的过程,然后使用保存的状态创建活动的新实例。这就是为什么有这么多onCreate和onCreateView调用的原因


我认为
onCreate
方法中的
if(savedInstanceState==null)
条件不是一个好主意;状态保存机制将无法正常工作…

是的,这是非常糟糕的记录。解释是当
活动
还原
时,它将“自动神奇地”
还原添加到其中的
片段
,因此,在您的
活动中添加
另一个
片段
基本上会在以前的
片段
上添加另一个新的
片段
,这些片段实际上是
Android
还原的

这种行为肯定是有意为之,而@Joris Wit建议的方法是正确的


当你考虑它的时候,这也是非常有用的,因为假设你有一堆
片段
,它们彼此叠加,你可以使用
back
键导航回它们。在轮换的情况下,如果
Android
无法恢复
片段的backbackback,您将丢失所有片段,或者您将必须实现某种机制来跟踪您的
片段
堆栈

看起来您的片段太多了! 若在xml文件中定义了片段,那个么就不能在代码中再次定义“它”! 有两种方法可以定义框架集:动态地(在代码中)和静态地(在xml中)! 请看这里:


这真是一个很好的教程。

主类应该扩展FragmentActivity而不是Activity


还可以在android文档中查找“活动生命周期”

如果您可以找到,请指向文档。谢谢。ApiDocs中有这样做的例子,但据我所知,在实际文档中没有解释。我在这方面找到的最正式的文档是以下示例:这非常明智!谢谢你指出这一点。正如我更愿意说的那样:实际上,您必须使用
android:configChanges=“orientation | screenSize”
作为清单中相关活动的
标记的属性。但是,不建议使用这种做法,
“应该避免并仅作为最后手段。”
这是我们单击您的链接时能看到的第一件事之一。
public class Right extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("Right", "onCreate()");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.i("Right", "onCreateView()");
        return inflater.inflate(R.layout.right, container, false);
    }
}
public class Main extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Fragment fg = new Right();
        getFragmentManager().beginTransaction().add(R.id.right_frag, fg)
            .commit();
        Log.i("Main", "onCreate()");
    }
}
08-28 21:47:38.220: INFO/Main(1099): onCreate()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreate()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:41.110: INFO/ActivityManager(142): Config changed: {1.0 0mcc0mnc en_US sw800dp w1280dp h752dp xlrg land finger -keyb/v/h -nav/h s.162}
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.170: INFO/Left(1099): onCreate()
08-28 21:47:41.170: INFO/Left(1099): onCreateView()
08-28 21:47:41.170: INFO/Main(1099): onCreate()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.190: INFO/Right(1099): onCreate()
08-28 21:47:41.190: INFO/Right(1099): onCreateView()
08-28 21:47:45.070: INFO/ActivityManager(142): Config changed: {1.0 0mcc0mnc en_US sw800dp w800dp h1232dp xlrg port finger -keyb/v/h -nav/h s.163}
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.130: INFO/Left(1099): onCreate()
08-28 21:47:45.130: INFO/Left(1099): onCreateView()
08-28 21:47:45.130: INFO/Main(1099): onCreate()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreate()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    if (savedInstanceState == null) {
        Fragment fg = new Right();
        getFragmentManager().beginTransaction().add(R.id.right_frag, fg)
            .commit();
    }
    Log.i("Main", "onCreate()");
}