더 이상 사용되지 않는 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 이전과 이후에 테스트 한 모든 경우에 ActivityContext버전 과 버전이 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()(에 onAttachFragment)하지만, 확인하는 것을 잊지 마세요 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.