Фрагмент загружается несколько раз при изменении ориентации

Когда я меняю ориентацию на эмуляторе или телефоне, фрагмент загружается еще раз. Если бы я повернул устройство 3 раза, фрагмент загрузился бы три раза после последнего вращения, если бы я повернул устройство 5 раз, оно загрузилось бы 5 раз после последнего вращения.

Основная деятельность

...
FragmentOne fragment = new FragmentOne();

FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.main_container, fragmnet);
transaction.commit();

Единственное, что у меня есть во фрагменте, это журналы, ничего, что могло бы вызвать многократную загрузку фрагмента. ФрагментОдин

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        Log.d(TAG, "onCreateView: ");
        return inflater.inflate(R.layout.fragment_fragment_one, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.d(TAG, "onViewCreated: ");
    }

Вот копия журнала после одного поворота, обратите внимание, что onCreateView вызывается несколько раз с одним изменением ориентации.

2020-04-13 01:23:07.396 10857-10857/com.example.myapplication D/MYFragmentOne: onCreate: 
2020-04-13 01:23:07.396 10857-10857/com.example.myapplication D/MYFragmentOne: onCreate: 
2020-04-13 01:23:07.418 10857-10857/com.example.myapplication D/MYMainActivity: onCreate: 
2020-04-13 01:23:07.423 10857-10857/com.example.myapplication D/MYFragmentOne: onCreateView: 
2020-04-13 01:23:07.429 10857-10857/com.example.myapplication D/MYFragmentOne: onViewCreated: 
2020-04-13 01:23:07.429 10857-10857/com.example.myapplication D/MYFragmentOne: onCreateView: 
2020-04-13 01:23:07.431 10857-10857/com.example.myapplication D/MYFragmentOne: onViewCreated: 
2020-04-13 01:23:07.431 10857-10857/com.example.myapplication D/MYFragmentOne: onCreate: 
2020-04-13 01:23:07.431 10857-10857/com.example.myapplication D/MYFragmentOne: onCreateView: 
2020-04-13 01:23:07.433 10857-10857/com.example.myapplication D/MYFragmentOne: onViewCreated:



App details
compileSdkVersion 29
buildToolsVersion "29.0.2"
applicationId "com.example.myapplication"
minSdkVersion 29
targetSdkVersion 29

Что могло заставить фрагмент загружаться так много раз с изменением ориентации?

Вот ссылка на мой github Link


person Shawn    schedule 13.04.2020    source источник


Ответы (2)


Когда ориентация активности изменится, она снова вызовет onCreate(), и фрагмент, который вы поместили в нее, также будет воссоздан. В этом случае вы должны создавать фрагмент только при первой загрузке активности. Затем получите сохраненный экземпляр фрагмента при следующей загрузке. Используйте tag в качестве клавиши Fragment.

private static final String FRAGMENT_TAG = "fragmentOne";

private Fragment fragment;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_settings)

    // savedInstanceState always null on activity's first load
    if (savedInstanceState == null) {
        fragment = new FragmentOne();
    } else {
        fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
    }

    getSupportFragmentManager().beginTransaction()
        .replace(R.id.main_container, fragment, FRAGMENT_TAG)
        .commit();
}
person Anggrayudi H    schedule 13.04.2020

Это происходит потому, что это «нормальное» поведение жизненного цикла Android. Когда вы переворачиваете телефон/экран, происходит смена ориентации, результатом чего является воссоздание активности. Есть несколько решений: первое — отключить ориентацию в файле манифеста, но это, вероятно, не то решение, которое вы ищете! Второй проверяет, добавлен ли уже фрагмент. Вы можете сделать что-то вроде:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MYMainActivity";
    private FragmentOne fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate: ");
        if (fragment == null) {
        fragment = new FragmentOne();

        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();


        transaction.add(R.id.main_container, fragment);
        transaction.commit();
        }
    }
}

В этом случае вы не будете добавлять несколько фрагментов при каждом воссоздании активности. Более того, вы можете проверить из диспетчера фрагментов, добавлен ли уже фрагмент из TAG, просто добавьте идентификатор в функцию transaction.add и проверьте, существует ли он!

Надеюсь, это поможет вам. Но в любом случае, просто нужно прочитать, как работает жизненный цикл Android для активности/фрагментов. Ваше здоровье

person DM developing    schedule 13.04.2020
comment
Мне трудно понять, как это проблема жизненного цикла фрагментов. Журнал, который я опубликовал, относится к одному изменению ориентации, onCreateView вызывается три раза, а onCreate вызывается один раз. Эти методы находятся в созданном состоянии жизненного цикла фрагмента, для меня они должны вызываться одинаковое количество раз. - person Shawn; 13.04.2020
comment
Как я уже сказал, похоже, что у вас так много разных экземпляров фрагментов в менеджере. Вы всегда добавляете фрагменты... Если вы знаете, как использовать профилировщик, просто проверьте, сколько существует экземпляров фрагментов. - person DM developing; 13.04.2020