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()
Ответы
Ответ 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
.
Ответ 3
Если вы не используете разные макеты для разных ориентаций, я думаю, что вы должны использовать android:configChanges="orientation"
в своем манифесте.
http://developer.android.com/guide/topics/manifest/activity-element.html#config
Ответ 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