Подтвердить что ты не робот

OnCreate() и onCreateView() вызывает намного больше, чем требуется (фрагменты)

Может кто-нибудь объяснить, почему вызовы onCreate() и onCreateView() вызываются столько раз, что увеличивается при изменении каждой ориентации?

Здесь очень простое приложение, состоящее из одного Activity, состоящего из двух Fragments. Второй Fragment динамически загружает . Если вы определяете эти два Fragments в main.xml, такого поведения не было бы.

Вот 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>

Left.class:

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

Ответ 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

Да, это очень плохо документировано. Объяснение состоит в том, что когда Activity равно restored, он будет "автоматически-магически" restore Fragments, который был добавлен в него, поэтому adding еще один Fragment в вашем Activity будет в основном добавлять другое новый Fragment поверх предыдущего Fragment\s, которые на самом деле restored на Android.

Это поведение определенно предназначено, и подход, предложенный @Joris Wit, является правильным.

Также это очень полезно, когда вы думаете об этом, потому что предположим, что у вас есть стек Fragments, добавленный один поверх другого, и вы можете вернуться к ним с помощью клавиши back. В случае вращения, если Android не восстановит стопку Fragments, вы потеряете все из них, или вам придется реализовать какой-то механизм для отслеживания вашего Fragment stack.

Ответ 4

Похоже, у вас так много фрагментов! Если вы определяете фрагмент в xml файле, вы не можете определить "он" снова в вашем коде! Существует два способа определения fragmets: dynamiclly (в вашем коде) и статически (в вашем xml)! Посмотрите здесь: http://marakana.com/s/post/1250/android_fragments_tutorial

Это действительно хороший учебник.

Ответ 5

Изменение ориентации заставляет систему проходить процесс сохранения состояния экземпляра, приостановки, остановки, уничтожения, а затем создания нового экземпляра активности с сохраненным состоянием. Так вот почему так много вызовов onCreate и onCreateView.

Я не думаю, что условие if (savedInstanceState == null) в методе onCreate является хорошей идеей; механизм экономии состояния не будет работать должным образом...

Ответ 6

Основной класс должен расширять FragmentActivity, а не Activity.

также найдите жизненный цикл активности в файле android doc