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

Почему Android O не работает с "не принадлежит этому FragmentManager!"

Я перенес свое приложение на Android O в Android Studio 3

Запуск на эмуляторе Android O всех моих диалоговых окон теперь не выполняется: -

java.lang.IllegalStateException: Fragment MyDialogFragment{43ccf50 #2 MyDialogFragment} declared target fragment SettingsFragment{ceed549 #0 id=0x7f0f0142 android:switcher:2131689794:0} that does not belong to this FragmentManager!
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1316)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1624)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1689)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:794)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2470)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2260)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2213)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2122)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:746)
at android.os.Handler.handleCallback(Handler.java:769)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6535)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

Я не делал никаких изменений кода.

Что изменилось в Android O, которое ранее работало с DialogFragments, теперь отображается?

Android Studio 3.0 Canary 1
Build #AI-171.4010489, built on May 15, 2017
JRE: 1.8.0_112-release-b736 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Mac OS X 10.11.6

    compileSdkVersion 'android-O'
    buildToolsVersion "26.0.0-rc2"

   AndroidManifest.xml
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 'O'
        }

compile 'com.android.support:appcompat-v7:26.0.0-beta1'
compile 'com.android.support:cardview-v7:26.0.0-beta1'
compile 'com.android.support:design:26.0.0-beta1'
    compile 'com.android.support:percent:26.0.0-beta1'

  dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha1'

    }
4b9b3361

Ответ 1

У меня была та же проблема, определенно ошибка андроида. Это происходит, когда вы показываете фрагмент из другого фрагмента, используя его как цель. В качестве обходного пути вы можете использовать:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    getActivity().getFragmentManager().beginTransaction().add(dialogFrag, "dialog").commit();
else
    getChildFragmentManager().beginTransaction().add(dialogFrag,"dialog").commit();

Ответ 2

Для меня это была не только проблема на Android O, но и в старых версиях. Самая старая версия, которую я тестировал, - это уровень API 16.

Я создавал свои фрагменты с помощью этого кода:

MyFragment myFragment = MyFragment.newInstance();
myFragment.setTargetFragment(ParentFragment.this, 0);
myFragment.show(getActivity().getSupportFragmentManager(), null);

Где ParentFragment.this - это произвольный класс, расширяющий android.support.v4.app.Fragment, MyFragment также расширяет этот класс и является дочерним фрагментом фрагмента ParentFragment (отсюда и название).

Я думал, что мне пришлось использовать SupportFragmentManager (метод getSupportFragmentManager()), потому что я использую фрагмент пакета поддержки, поэтому я попытался вызвать getActivity().getSupportFragmentManager(), чтобы получить ссылку на действие, которая поддерживает этот метод.

Это не похоже на правильный путь. Я изменил эти вызовы на:

MyFragment myFragment = MyFragment.newInstance();
myFragment.setTargetFragment(ParentFragment.this, 0);
myFragment.show(getFragmentManager(), null);

поэтому фрагмент решает сам, какой FragmentManager использовать, и ошибка исчезла.

Надеюсь, это поможет кому-то.

Ответ 3

Я только столкнулся с теми же проблемами в проекте, над которым я сейчас работаю, когда мы перешли на Android Studio 3 и обновили библиотеку поддержки до версии 26. Внезапно, без изменения кода, мы получили тонны этого исключения. В итоге я узнал следующее:

В январе этого года Google добавил новую "проверку работоспособности" в исходные тексты Менеджера фрагментов v4 (не уверен, в какую версию вышел), который отказывается добавлять фрагмент с помощью Менеджера фрагментов, если у него есть набор целевых фрагментов и цель. фрагмент не может быть найден в активных фрагментах того же менеджера фрагментов. Патч подробно описан здесь

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

Ответ 4

У меня был тот же случай, что и у Маркуса Реселя, но я использовал getChildFragmentManager(). Я заменил это на getFragmentManager(), и это решило проблему.

ОБНОВЛЕНИЕ: я теперь работаю с childFragmentManager и имею некоторую обратную связь.

При работе с внутренними фрагментами, которые размещены фрагментом (например, фрагментом внутри фрагмента), используйте childFragmentManager. Этот менеджер фрагментов отличается от действий getSupportFragmentManager. Два не одинаковы. Это разделение интересов.

Поэтому я установил правило, что фрагменты, содержащие дочерние фрагменты, всегда будут использовать childFragmentManager, а вещи, находящиеся вне фрагментов хоста, могут использовать getSupportfragmentManager.

Ответ 5

мое приложение работает хорошо до обновления целевой версии до 27, тогда я сталкиваюсь с той же проблемой при вызове setTargetFragment (фрагмент фрагмента, int requestCode)

пример:

chooseRegionFragment.setTargetFragment(ParentFragment.this, REQUEST_CODE_CHOOSE_REGION); 

просто измените на:

chooseRegionFragment.setTargetFragment(getRootParentFragment(this), REQUEST_CODE_CHOOSE_REGION);

getRootParentFragment(this) этот метод найдет для вас корневой родительский фрагмент

/** 
   * find root parent of fragment 
   */ 
  public static Fragment getRootParentFragment(Fragment fragment) { 
    Fragment parent = fragment.getParentFragment(); 
    if(parent == null) 
      return fragment; 
    else 
      return getRootParentFragment(parent); 
  } 

Ответ 6

Недавно у моего приложения возникла та же проблема, когда я настроил его для Android O. В качестве решения используйте:

myDialogFragment.show(SettingsFragment.this.getFragmentManager(), TAG);

вместо:

myDialogFragment.show(getFragmentManager(), TAG);
// or  
myDialogFragment.show(getSupportFragmentManager(), TAG);
// or  
myDialogFragment.show(getChildFragmentManager(), TAG);