Фрагмент Android onAttach() устарел

Я обновил свое приложение, чтобы оно использовало последнюю версию библиотеки поддержки (версия 23.0.0), и обнаружил, что они устарели в функции onAttach() класса Fragment.

Вместо:

onAttach (Activity activity)

Это снег:

onAttach (Context context)

Поскольку мое приложение использует активность, переданную до устаревания, я думаю, что возможное решение:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    activity = getActivity();
}

Это был бы правильный способ сделать это?

ОБНОВИТЬ:

Если я запускаю устройство с API ниже 23, новый onAttach() даже не вызывается. Я надеюсь, что это не то, что они намеревались сделать!

ОБНОВЛЕНИЕ 2:

Проблема была решена с последними обновлениями в SDK.

Я проверил на своем устройстве API 22 и вызывается onAttach(Context).

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

9 ответов

Решение

Активность - это контекст, поэтому, если вы можете просто проверить, что контекст - это Активность, и при необходимости разыграть его.

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity a;

    if (context instanceof Activity){
        a=(Activity) context;
    }

}

Обновление: некоторые утверждают, что новый Context переопределение никогда не вызывается. Я провел несколько тестов и не могу найти сценарий, где это правда, и в соответствии с исходным кодом, это никогда не должно быть правдой. Во всех случаях, которые я тестировал, до и после SDK23, оба Activity и Context версии onAttach были позваны. Если вы можете найти сценарий, в котором это не так, я бы предложил вам создать пример проекта, иллюстрирующий проблему, и сообщить об этом команде Android.

Обновление 2: я использую только фрагменты библиотеки поддержки Android, так как ошибки там исправляются быстрее. Кажется, вышеупомянутая проблема, где переопределения не вызываются правильно, выявляется, только если вы используете фрагменты каркаса.

Это еще одно отличное изменение от Google ... Предлагаемая модификация: заменить onAttach(Activity activity) с onAttach(Context context) разбил мои приложения на старых API, так как onAttach(Context context) не будут вызываться на родные фрагменты.

Я использую нативные фрагменты (android.app.Fragment), поэтому мне пришлось сделать следующее, чтобы он снова работал на старых API (< 23).

Вот что я сделал:

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    // Code here
}

@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        // Code here
    }
}

Если вы используете фрагменты фреймворка и версия SDK устройства ниже 23, OnAttach(Context context) не будет назван.

Вместо этого я использую вспомогательные фрагменты, поэтому исправление onAttach(Context context) всегда вызывается.

В настоящее время из onAttach Фрагмент кода, не ясно, если Context текущая активность: Исходный код

public void onAttach(Context context) {
    mCalled = true;
    final Activity hostActivity = mHost == null ? null : mHost.getActivity();
    if (hostActivity != null) {
        mCalled = false;
        onAttach(hostActivity);
    }
}

Если вы посмотрите на getActivity вы увидите тот же звонок

/**
 * Return the Activity this fragment is currently associated with.
 */
final public Activity getActivity() {
    return mHost == null ? null : mHost.getActivity();
}

Так что, если вы хотите быть уверены, что получаете Активность, используйте getActivity()onAttach в вашем Fragment) но не забудьте проверить null потому что, если mHost является null ваша деятельность будет null

Хотя кажется, что в большинстве случаев достаточно иметь onAttach(Context)Есть некоторые телефоны (например, Xiaomi Redme Note 2), где он не вызывается, поэтому он вызывает исключения NullPointerException. Поэтому, чтобы быть в безопасности, я предлагаю также оставить устаревший метод:

// onAttach(Activity) is necessary in some Xiaomi phones
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    _onAttach(activity);
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    _onAttach(context);
}

private void _onAttach(Context context) {
    // do your real stuff here
}
@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity activity = context instanceof Activity ? (Activity) context : null;
}

Загрузите новейшую библиотеку поддержки с менеджером SDK и включите

compile 'com.android.support:appcompat-v7:23.1.1'

в gradle.app и установите версию компиляции на API 23

Ответ ниже относится к этому предупреждению об устаревании, встречающемуся в учебном руководстве по фрагментам на веб-сайте разработчика Android, и может не относиться к постам выше.

Я использовал этот код на уроке, и он сработал.

public void onAttach(Context context){
    super.onAttach(context);

    Activity activity = getActivity();

Я волновался, что активность может быть нулевой, как указано в документации.

getActivity

FragmentActivity getActivity () Возвращает FragmentActivity, с которым в данный момент связан этот фрагмент. Может возвратить нуль, если фрагмент связан с Контекстом вместо этого.

Но onCreate для main_activity четко показывает, что фрагмент был загружен, и поэтому после этого метода вызов действия get из фрагмента вернет класс main_activity.

getSupportFragmentManager (). beginTransaction ().add (R.id.fragment_container, firstFragment).commit ();

Я надеюсь, что я прав с этим. Я абсолютный новичок.

Вы, вероятно, используете android.support.v4.app.Fragment, Для этого вместо onAttach метод, просто используйте getActivity() чтобы получить FragmentActivity с которым фрагмент связан с. Иначе вы могли бы использовать onAttach(Context context) метод.

Это сработало для меня, когда у меня есть пользовательский интерфейс TopSectionListener, его объект activitycommander:

  //This method gets called whenever we attach fragment to the activity
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    Activity a=getActivity();
    try {
        if(context instanceof Activity)
           this.activitycommander=(TopSectionListener)a;
    }catch (ClassCastException e){
        throw new ClassCastException(a.toString());}

}
Другие вопросы по тегам