【问题标题】:onCreate() and onCreateView() invokes a lot more than required (Fragments)onCreate() 和 onCreateView() 调用比需要的多得多(片段)
【发布时间】:2011-08-28 18:57:56
【问题描述】:

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

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

这里是main.xml

       <fragment class="ets.saeref.Left"
        android:id="@+id/left_frag"
        android:layout_weight="70"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

     <FrameLayout android:id="@+id/right_frag" 
        android:layout_weight="30"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"/>

</LinearLayout>

这是剩下的片段:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent" android:background="#000000">
    <Button android:text="Landscape" android:id="@+id/button1"
        android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

</LinearLayout>

这是正确的片段:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent" android:background="#ffffff">
    <Button android:text="Landscape" android:id="@+id/button1"
        android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

</LinearLayout>

左类:

public class Left extends Fragment {

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.i("Left", "onCreateView()");
        return inflater.inflate(R.layout.left, container, false);
    }
}

Right.class:

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()

【问题讨论】:

    标签: android


    【解决方案1】:

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

    @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()");
    }
    

    【讨论】:

    【解决方案2】:

    是的,这是非常糟糕的记录。解释是,当Activityrestored 时,它会“自动”在其中添加restore Fragments,所以adding 另一个Fragment 在你的Activity 中基本上会添加另一个新的Fragment 位于之前的Fragment\s 之上,实际上是Androidrestored

    这种行为绝对是有意的,@Joris Wit 建议的方法是正确的。

    当您考虑它时,这也非常有用,因为假设您有一堆 Fragments 彼此叠加,您可以使用 back 键导航回它们。在轮换的情况下,如果Android 无法恢复Fragments 的后台堆栈,您将失去所有这些,或者您将不得不实施某种机制来跟踪您的Fragment stack

    【讨论】:

      【解决方案3】:

      如果您不针对不同的方向使用不同的布局,我认为您应该在清单中使用android:configChanges="orientation"http://developer.android.com/guide/topics/manifest/activity-element.html#config

      【讨论】:

      • 这非常明智!感谢您指出这一点。当事情说清楚时,我更喜欢:实际上,您必须在清单中使用 android:configChanges="orientation|screenSize" 作为相关活动的 &lt;activity&gt; 标记的属性。
      • 然而,不推荐这种做法,"should be avoided and used only as a last resort." 这是我们点击您的链接时首先看到的内容之一。
      【解决方案4】:

      看起来你那里有很多碎片! 如果您在 xml 文件中定义片段,您不能在您的代码中再次定义“它”! 定义片段有两种方法:dynamiclly(在您的代码中)和静态(在您的 xml 中)! 看看这里: http://marakana.com/s/post/1250/android_fragments_tutorial

      真的是很好的教程。

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          主类应该扩展 FragmentActivity 而不是 Activity。

          还可以在 android 文档上查找 Activity 生命周期

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-17
            相关资源
            最近更新 更多