더 이상 사용되지 않는 Android Fragment onAttach ()


326

최신 지원 라이브러리 (버전 23.0.0)를 사용하도록 앱을 업데이트했는데 Fragment 클래스의 onAttach () 함수가 더 이상 사용되지 않는다는 것을 알았습니다.

대신에:

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 직원의 답변을 보려면 여기 를 클릭 하십시오 .


전달 된 인스턴스에서 특정 활동 메소드를 사용하는 경우 컨텍스트를 활동으로 캐스팅하려고 했습니까? 활동은 컨텍스트의 서브 클래스임을 기억하십시오. 아마도 캐스팅이 작동했을 것입니다.
— MarkSkayff

어떤 이유로 onAttach ()도 호출되지 않습니다! 어떤 아이디어? 최신 지원 라이브러리로 업데이트하셨습니까?
— TareK Khoury

2
왜 API가로 이동 Context했습니까? Activity어쨌든 조각을 첨부하고 표시하기 위해가 필요하지 않습니까? 다른 방법으로 Context매개 변수 를 사용 하시겠습니까?
— Kenny Worden

1
내가 링크 참조 버그로 게시 code.google.com/p/android/issues/detail?id=183358
— 타렉 쿠리을

6
새 항목 onAttach(Context context)을 호출하려면 API 23 이상의 장치를 사용하거나 android.support.v4.app.Fragment를 사용해야합니다. 여기
— nevzo

답변:


337

활동은 컨텍스트이므로 컨텍스트가 활동인지 간단히 확인하고 필요한 경우 캐스트하십시오.

@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 지원 라이브러리 조각 만 사용합니다. 프레임 워크 조각을 사용하는 경우 재정의가 올바르게 호출되지 않는 위의 문제 만 나타납니다.


5
컨텍스트가있는 onAttach가 활동이있는 onAttach와 같은 방식으로 호출되지 않으므로 실제로 솔루션이 아닙니다. 매개 변수로 활동이있는 onAttach에 초기화 코드가 있으면이 변경 사항이 적용되지 않습니다.
— 버디

2
아니요, 적어도 제 경우에는 동일하게 작동하지 않습니다. onAttach에서 활동이나 컨텍스트를 사용하지 않고 초기화를 수행합니다. onAttach를 컨텍스트가있는 액티비티로 바꾸려고 시도했지만 같은 방식으로 호출되지 않습니다. 그래서 그들은 쉽게 상호 교환 할 수 없습니다.
— 버디

7
버디가 겪었던 것과 같은 문제는 ... onAttach(Context)부르지 않는 것 같습니다.
— Stéphane

2
코드를 단계별로 실행했으며 onAttach(context)호출 할 수 없는지 확인할 수 있습니다 .
— 채드 빙엄

2
필자의 경우 이전에 시스템에서 지운 활동을 다시 시작하면 onAttach ()가 호출되지 않습니다. 그러나 항상 이런 것은 아닙니다. onAttach (Context context), refActivity = new WeakReference <> ((AppCompatActivity) 컨텍스트)에 WeakReference의 초기화를 넣었습니다. 그리고 때로는 onCreateView ()에서 NullPointerException이 발생합니다.
— Kimi Chiu

45

이것은 Google의 또 다른 큰 변화입니다 ... 제안 된 수정 : 기본 조각에서 호출되지 않으므로 이전 API에서 내 앱 onAttach(Activity activity)이 onAttach(Context context)충돌로 바뀝니다 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
    }
}

Mr.Yoann Hercouet, API 23 이상에서 수행하는 방법을 설명해 주시면 감사하겠습니다. android.support.v4.app.FragmentManagerImpl.execSingleAction에서 support.v4.app.FragmentManagerImpl.moveToState. 여기에 나는 내 버그를 알기 위해 필요한 줄을 게시했습니다.
— MohanRaj S

@MohanRajS 코드 24에 따르면 API 24 (내가 사용한 것)와 동일합니다. 문제는 이것으로 아무것도 할 필요가없는 것 같습니다.
— Yoann Hercouet

@ YooHercouet, 당신의 회신 감사합니다, 확인 및 업데이트.
— MohanRaj S

1
오래된 API를 타겟팅하기가 어렵 기 때문에 Google에 만족하지 않습니다. 예를 들어, 애플은 예전 API를 목표로 삼을 수있는 축복을 생각해 보자. 예를 들어, 애플은 당신을 엄청나게 무너 뜨리고 새로운 것만 지원하도록 강요 할 것이다.
— Stan

39

프레임 워크 조각을 사용하고 장치의 SDK 버전이 23보다 낮 으면 OnAttach(Context context)호출되지 않습니다.

대신 지원 조각을 사용하므로 사용 중단이 수정되어 onAttach(Context context)항상 호출됩니다.


11

현재 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


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

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

5

대부분의 경우 충분할 것 같지만 onAttach(Context)호출되지 않는 전화 (예 : Xiaomi Redme Note 2)가 있으므로 NullPointerExceptions이 발생합니다. 따라서 안전한면을 유지하기 위해 더 이상 사용되지 않는 방법을 남겨 두는 것이 좋습니다.

// 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
}

3

SDK 관리자와 함께 최신 지원 라이브러리를 다운로드하고 포함

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

gradle.app에서 컴파일 버전을 API 23으로 설정


1

아래 답변은 Android 개발자 웹 사이트의 조각 튜토리얼에서 발생하는이 지원 중단 경고와 관련이 있으며 위의 게시물과 관련이 없을 수 있습니다.

튜토리얼 수업 에서이 코드를 사용했으며 효과가있었습니다.

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

    Activity activity = getActivity();

나는 문서가 말한 것처럼 활동이 무효가 될까 걱정했다.

getActivity

FragmentActivity getActivity ()이 프래그먼트가 현재 관련되어있는 FragmentActivity를 리턴합니다. 프래그먼트가 대신 컨텍스트와 연관된 경우 널을 리턴 할 수 있습니다.

그러나 main_activity의 onCreate는 조각이로드되었음을 명확하게 표시하므로이 메소드 후에 조각에서 get 활동을 호출하면 main_activity 클래스가 리턴됩니다.

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

나는 이것이 정확하기를 바랍니다. 나는 절대 초보자입니다.


1

당신은 아마 사용하고 android.support.v4.app.Fragment있습니다. 이 onAttach방법 대신에 , 프래그먼트와 관련된를 getActivity()얻기 위해 사용 하십시오 FragmentActivity. 그렇지 않으면 onAttach(Context context)방법을 사용할 수 있습니다 .


0

이것은 객체 활동 커맨더 인 사용자 정의 인터페이스 'TopSectionListener'를 가지고있을 때 나를 위해 일했습니다.

  //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());}

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.