Android - onAttach (Контекст), не вызываемый API 23

Я обновил SDK до последней версии (API 23), а метод onAttach(Activity) для фрагмента устарел. Поэтому вместо использования этого метода теперь я использую onAttach(Context), но этот не вызывается в течение жизненного цикла. Действие представляет собой экземпляр AppCompatActivity из v7, а фрагмент представляет собой экземпляр класса Fragment (android.app.Fragment).

Любые идеи о том, как заставить onAttach работать в API 23?

Решение

Я нашел несколько ответов, которые помогут вам понять и исправить эту проблему:

Как я уже говорил до того, как я использовал активность из поддержки v7 (AppCompatActivity) и фрагмента из android.app.
Для отображения фрагментов я получаю диспетчер фрагментов, используя метод getFragmentManager для активности, поэтому диспетчер фрагментов является экземпляром FragmentManager из android.app → и вот проблема
Если вы запустите приложение на устройстве с API 23 (Ive запустите его в AS Emulator), вы увидите, что будет вызван метод onAttach (Context). Во время процесса отображения фрагмента FragmentManager в определенный момент вызывается метод onAttach (..). Используя getFragmentManager(), вы получите экземпляр диспетчера фрагментов, доступный для версии Android, которая запущена на этом устройстве (например, API 22, 23). В случае, если приложение работает на устройстве с API < 23 метод onAttach (Контекст) недоступен, менеджер фрагментов не знает, что в API 23 существует метод onAttach (Context), поэтому поэтому он не вызывается для API < 23 → решение для подобных задач использует FragmentManager из библиотек поддержки.

Решения:

  • Использование getSupportFragmentManager() заставит вас использовать фрагмент из библиотеки поддержки. Итак, первое решение - заменить все фрагменты фрагментом из lib и использовать getSupportFragmentManager().

  • Решение, которое я уже реализовал, состоит в том, чтобы обрабатывать 2 возможности (1. приложение работает на устройстве с API < 23, приложение работает на устройстве с API >= 23).

Вкратце, в моей реализации у меня есть базовый класс для всех фрагментов из проекта, и я добавил туда этот код:

/*
 * onAttach(Context) is not called on pre API 23 versions of Android and onAttach(Activity) is deprecated
 * Use onAttachToContext instead
 */
@TargetApi(23)
@Override
public final void onAttach(Context context) {
    super.onAttach(context);
    onAttachToContext(context);
}

/*
 * Deprecated on API 23
 * Use onAttachToContext instead
 */
@SuppressWarnings("deprecation")
@Override
public final void onAttach(Activity activity) {
    super.onAttach(activity);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        onAttachToContext(activity);
    }
}

/*
 * Called when the fragment attaches to the context
 */
protected void onAttachToContext(Context context) {
}

Теперь я просто переопределяю метод onAttachToContext (Context) на всех фрагментах, где мне это нужно.

Ответ 1

Я решил проблему таким образом:

@TargetApi(23)
@Override public void onAttach(Context context) {
    //This method avoid to call super.onAttach(context) if I'm not using api 23 or more
    //if (Build.VERSION.SDK_INT >= 23) {
        super.onAttach(context);
        onAttachToContext(context);
    //}
}

/*
 * Deprecated on API 23
 * Use onAttachToContext instead
 */
@SuppressWarnings("deprecation")
@Override public void onAttach(Activity activity) {
    super.onAttach(activity);
    if (Build.VERSION.SDK_INT < 23) {
        onAttachToContext(activity);
    }
}

/*
 * This method will be called from one of the two previous method
 */
protected void onAttachToContext(Context context) {}

Ответ 2

Вам следует попробовать использовать версию библиотеки поддержки Fragment.

Вам нужно переключиться на import android.support.v4.app.Fragment; вместо import android.app.Fragment;. Вам также нужно убедиться, что вы используете getSupportFragmentManager() вместо getFragmentManager().

Ответ 3

Я столкнулся с той же проблемой. У меня есть minSdkVersion 19 и targetSdkVersion из 23, и я использую fragmentManager в AppCompatActivity.

onAttach(Activity activity) отмечен как устаревший, но я столкнулся с авариями приложений, когда я заменил его на onAttach(Context context).

Поэтому вместо этого у меня теперь обе версии присутствуют, и когда я запускаю свое приложение в API22, onAttach(Activity activity) запускается, хотя он отмечен как устаревший.

Я не тестировал его на устройстве Android Marshmallow, но я понимаю, что он запускает версию onAttach(Context context), игнорируя другую.

Обновить, чтобы принять во внимание наблюдение @skaar в комментариях ниже: Теперь я могу протестировать API23 и подтвердить, что запуск на платформе 23 вызывает вызовы обоих методов (с Activity и Context). Спасибо за головы!

Ответ 4

просьба сообщить об этом BUG здесь

ВЫПУСК, ОТКРЫТЫЙ НА ПРОЕКТЕ GOOGLE AOSP:

https://code.google.com/p/android/issues/detail?id=185465

пс. это не ваша работа, чтобы найти решение этой проблемы и найти какие-то способы обхода... но заставить Google исправить свой сломанный API! для этого вам нужно жаловаться, как я сказал.

связанная проблема - getContext() из фрагмента:

https://code.google.com/p/android/issues/detail?id=185848

Ответ 5

После того, как я прочитал ваш ответ @David Rauca Я думаю, что второй может решить мою проблему. Но, когда я смотрю в исходный код. Я обнаружил, что на самом деле onAttach(Context context) ничего не делает на Android M, просто вызвал старый метод.

В качестве решения:

@SuppressWarnings("deprecation")

Просто добавьте его в старый метод - лучшее решение.

Ответ 6

Я столкнулся с той же проблемой. Что я сделал для его решения:

  • Измените тип аргумента onAttach callback от Activity до Контекст. По неизвестной причине это изменение приводит к тому, что метод onAttach (Контекст) больше не вызывается во время жизненного цикла фрагмента. Как следствие, мое приложение рушилось, так как код, который был в onAttach метод никогда не выполнялся.

  • Переместите код, который был в методе onAttach, в onCreate, поскольку он   все еще выполняется.

С этой модификацией приложение становится функционировать по-прежнему. Никаких дополнительных инструкций import не требуется.