[java] onPause, onStop 및 onDestroy 메서드에서 슈퍼 클래스 메서드를 호출하는 올바른 순서는 무엇입니까? 그리고 왜?

방금 Android 개발자 사이트를 살펴보고 활동 수명주기를 새로 고쳤습니다. 각 코드 예제에는 “항상 수퍼 클래스 메서드를 먼저 호출하십시오”라는 주석이 수퍼 클래스 메서드 옆에 있습니다.

생성 반주기 onCreate, onStart 및 onResume에서는 이것이 의미가 있지만 파괴 반주기의 올바른 절차 인 onPause, onStop, onDestroy에 대해 약간 혼란 스럽습니다.

인스턴스 특정 리소스가 의존 할 수있는 슈퍼 클래스 리소스를 파괴하기 전에 먼저 인스턴스 특정 리소스를 파괴하는 것이 합리적이며 그 반대가 아닙니다. 내가 무엇을 놓치고 있습니까?

편집 : 사람들이 질문의 의도에 대해 혼란스러워하는 것 같아서 내가 알고 싶은 것은 다음 중 올바른 것은 무엇입니까? 그리고 왜 ?

1. Google 제안

    @Override
    protected void onStop() {
      super.onStop();  // Always call the superclass method first

      //my implementation here
    }

2. 다른 방법

    @Override
    protected void onStop() {
       //my implementation here

       super.onStop();
    }



답변

인스턴스 특정 리소스가 의존 할 수있는 수퍼 클래스 리소스를 파괴하기 전에 먼저 인스턴스 특정 리소스를 파괴하는 것이 합리적입니다. 그러나 의견은 그렇지 않다는 것을 암시합니다. 내가 무엇을 놓치고 있습니까?

제 생각에는 하나도 아닙니다.

Mark (일명 CommonsWare on SO)의이 답변은 문제에 대해 밝힙니다. Link- 수퍼 클래스 메서드에 대한 호출이 첫 번째 문이어야합니까? . 그러나 그의 답변에 다음과 같은 댓글이 남았습니다.

그러나 왜 공식 문서에서 onPause ()에서 “항상 수퍼 클래스 메서드를 먼저 호출”이라고 말하는가?

원점으로 돌아가다. 좋아요, 이것을 다른 각도에서 봅시다. Java 언어 사양 호출을 super.overridenMethod()해야하는 순서 (또는 호출을 수행 해야하는 경우) 를 지정 하지 않습니다 .

클래스 Activity의 경우 super.overridenMethod()호출이 필요하고 적용됩니다 .

if (!mCalled) {
    throw new SuperNotCalledException(
        "Activity " + mComponent.toShortString() +
            " did not call through to super.onStop()");
}

mCalled에서 true로 설정됩니다 Activity.onStop().

이제 토론해야 할 유일한 세부 사항은 주문입니다.

I also know that both work

확실한. Activity.onPause ()에 대한 메서드 본문을 살펴보십시오.

protected void onPause() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);

    // This is to invoke 
    // Application.ActivityLifecyleCallbacks.onActivityPaused(Activity)
    getApplication().dispatchActivityPaused(this);

    // The flag to enforce calling of this method
    mCalled = true;
}

어떤 식으로 전화를 super.onPause()걸어도 괜찮을 것입니다. Activity.onStop ()에는 유사한 메서드 본문이 있습니다. 그러나 Activity.onDestroy ()를 살펴보십시오.

protected void onDestroy() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
    mCalled = true;

    // dismiss any dialogs we are managing.
    if (mManagedDialogs != null) {
        final int numDialogs = mManagedDialogs.size();
        for (int i = 0; i < numDialogs; i++) {
            final ManagedDialog md = mManagedDialogs.valueAt(i);
            if (md.mDialog.isShowing()) {
                md.mDialog.dismiss();
            }
        }
        mManagedDialogs = null;
    }

    // close any cursors we are managing.
    synchronized (mManagedCursors) {
        int numCursors = mManagedCursors.size();
        for (int i = 0; i < numCursors; i++) {
            ManagedCursor c = mManagedCursors.get(i);
            if (c != null) {
                c.mCursor.close();
            }
        }
        mManagedCursors.clear();
    }

    // Close any open search dialog
    if (mSearchManager != null) {
        mSearchManager.stopSearch();
    }

    getApplication().dispatchActivityDestroyed(this);
}

여기서 순서는 활동이 설정되는 방법과 호출 이 다음 코드를 방해 하는지 여부에 따라 중요 할 수 있습니다super.onDestroy() .

마지막으로, 진술 Always call the superclass method first은 그것을 뒷받침 할 증거가 많지 않은 것 같습니다. 더 나쁜 것은 (문의 경우) 다음 코드가 다음에서 가져온 것입니다 android.app.ListActivity.

public class ListActivity extends Activity {

    ....

    @Override
    protected void onDestroy() {
        mHandler.removeCallbacks(mRequestFocus);
        super.onDestroy();
    }
    ....
}

그리고 Android SDK에 포함 된 LunarLander 샘플 애플리케이션에서 :

public class LunarLander extends Activity {

    ....

    @Override
    protected void onPause() {
        mLunarView.getThread().pause(); // pause game when Activity pauses
        super.onPause();
    }
    ....
}

요약 및 가치있는 언급 :

사용자 Philip Sheard : super.onPause()활동이을 (를) 사용하여 시작한 경우 호출을 지연해야하는 시나리오를 제공합니다 startActivityForResult(Intent). 사용하여 결과 설정 setResult(...) super.onPause() 작동하지 않습니다를. 그는 나중에 그의 답변에 대한 의견에서 이에 대해 명확히 설명합니다.

사용자 Sherif elKhatib : 수퍼 클래스가 먼저 리소스를 초기화하고 마지막에 논리에서 리소스를 파괴하도록하는 이유를 설명합니다.

위치를 제공하는 getLocation () 함수가 포함 된 LocationActivity가있는 다운로드 한 라이브러리를 고려해 보겠습니다. 대부분의 경우이 액티비티는 onCreate ()에서 항목을 초기화해야하므로 super.onCreate를 먼저 호출해야합니다 . 당신은 그것이 의미가 있다고 느끼기 때문에 이미 그렇게하고 있습니다. 이제 onDestroy에서 SharedPreferences 어딘가에 위치를 저장하기로 결정했습니다. super.onDestroy를 먼저 호출하면 LocationActivity의 구현이 onDestroy의 위치 값을 무효화하기 때문에 getLocation이이 호출 후에 null 값을 반환 할 가능성이 어느 정도 있습니다. 아이디어는 이런 일이 발생하더라도 당신이 그것을 비난하지 않을 것이라는 것입니다.따라서 자신의 onDestroy를 완료 한 후 마지막에 super.onDestroy를 호출합니다.

그는 계속해서 지적합니다. 만약 자식 클래스가 부모 클래스로부터 적절하게 분리되어 있다면 (자원 의존성 측면에서), super.X()호출은 어떤 주문 사양을 따를 필요가 없습니다.

배치 어디 시나리오를 읽고이 페이지에 자신의 답변을 참조 super.onDestroy()호출 않는 프로그램 로직에 영향을 미칩니다.

Mark의 답변에서 :

구성 요소 생성의 일부인 재정의하는 메서드 (onCreate (), onStart (), onResume () 등), 첫 번째 문으로 수퍼 클래스에 연결하여 Android가 먼저 작업을 수행 할 수 있도록해야합니다. 수행 된 작업에 의존하는 작업을 시도합니다.

컴포넌트 파괴 (onPause (), onStop (), onDestroy () 등)의 일부인 메서드를 재정의하면 먼저 작업을 수행하고 마지막으로 수퍼 클래스에 연결해야합니다 . 이렇게하면 Android가 작업에 의존하는 항목을 정리하는 경우 먼저 작업을 수행 한 것입니다.

void (onCreateOptionsMenu () 등) 이외의 것을 반환하는 메서드는 특정 반환 값을 강제하는 데 필요한 작업을 특별히 수행하지 않는다고 가정하여 때때로 return 문에서 수퍼 클래스에 연결합니다.

onActivityResult ()와 같은 다른 모든 것은 전체적으로 귀하에게 달려 있습니다. 우선 수퍼 클래스에 연결하는 경향이 있지만 문제가 발생하지 않는 한 나중에 연결하는 것이 좋습니다.

밥 컨스 에서 이 스레드 :

좋은 패턴 [(마크가 위에서 제안한 패턴)]이지만 몇 가지 예외를 발견했습니다. 예를 들어,
PreferenceActivity에 적용하고 싶은 테마는 수퍼 클래스의 onCreate () 앞에 놓지 않으면 효과가 없습니다.

사용자 Steve Benett 도 이에 대해주의를 기울입니다.

나는 슈퍼 콜의 타이밍이 필요한 한 가지 상황만을 알고 있습니다. onCreate에서 테마 또는 디스플레이 등의 표준 동작을 변경하려면 super를 호출하여 효과를 확인하기 전에 변경해야합니다 . 그렇지 않으면 AFAIK를 호출하는 시간에 차이가 없습니다.

사용자 Sunil Mishra 는 Activity 클래스의 메서드를 호출 할 때 순서 (거의 가능성이 높음)가 역할을하지 않는다는 것을 확인합니다. 그는 또한 슈퍼 클래스 메서드를 먼저 호출하는 것이 모범 사례라고 주장합니다 . 그러나 나는 이것을 확증 할 수 없었다.

사용자 LOG_TAG : 슈퍼 클래스 생성자 호출이 다른 모든 것보다 우선해야하는 이유를 설명합니다 . 제 생각에는이 설명이 질문에 추가되지 않습니다.

끝 메모 : 신뢰 하지만 확인하십시오. 이 페이지에있는 대부분의 답변은이 접근 방식을 따라 문 Always call the superclass method first에 논리적 근거가 있는지 확인합니다 . 밝혀진대로 그렇지 않습니다. 적어도 Activity 클래스의 경우는 아닙니다. 일반적으로 super의 메서드에 대한 호출 순서가 요구 사항인지 확인하려면 수퍼 클래스의 소스 코드를 읽어야합니다.


답변

(당신이 말했듯이) super onCreate를 먼저 호출하는 것이 합리적이므로 생각해보십시오.

내가 만들고 싶을 때, 내 수퍼가 리소스를 생성하고> 내 리소스를 생성합니다.

반대로 : (일종의 스택)

내가 파괴하고 싶을 때, 나는 내 자원을 파괴합니다.> 나의 수퍼가 그의 자원을 파괴합니다.


이러한 의미에서 두 가지 함수 (onCreate / onDestroy, onResume / onPause, onStart / onStop)에 적용됩니다. 당연히 onCreate는 리소스를 생성하고 onDestroy는 이러한 리소스를 해제합니다. 그건 그렇고, 다른 커플에게도 같은 증거가 적용됩니다.

위치를 제공하는 getLocation () 함수를 포함하는 LocationActivity가있는 다운로드 한 라이브러리를 고려해 보겠습니다. 아마도이 액티비티는 onCreate ()에서 항목을 초기화해야 할 것입니다. 그러면 super.onCreate를 먼저 호출해야합니다. 당신은 그것이 의미가 있다고 느끼기 때문에 이미 그렇게하고 있습니다. 이제 onDestroy에서 SharedPreferences 어딘가에 위치를 저장하기로 결정했습니다. super.onDestroy를 먼저 호출하면 LocationActivity의 구현이 onDestroy의 위치 값을 무효화하기 때문에 getLocation이이 호출 후에 null 값을 반환 할 가능성이 어느 정도 있습니다. 아이디어는 이런 일이 발생해도 당신이 그것을 비난하지 않을 것이라는 것입니다. 따라서 자신의 onDestroy를 완료 한 후 마지막에 super.onDestroy를 호출합니다. 나는 이것이 약간 의미가 있기를 바랍니다.

위의 내용이 타당하다면 언제든지 위의 개념을 준수하는 활동이 있다는 것을 고려하십시오. 이 활동을 확장하고 싶다면, 똑같은 주장 때문에 같은 방식으로 느끼고 같은 순서를 따를 것입니다.

귀납법으로 모든 활동은 똑같은 일을해야합니다. 다음은 이러한 규칙을 따라야하는 활동에 대한 좋은 추상 클래스입니다.

package mobi.sherif.base;

import android.app.Activity;
import android.os.Bundle;

public abstract class BaseActivity extends Activity {
    protected abstract void doCreate(Bundle savedInstanceState);
    protected abstract void doDestroy();
    protected abstract void doResume();
    protected abstract void doPause();
    protected abstract void doStart();
    protected abstract void doStop();
    protected abstract void doSaveInstanceState(Bundle outState);
    @Override
    protected final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        doCreate(savedInstanceState);
    }
    @Override
    protected final void onDestroy() {
        doDestroy();
        super.onDestroy();
    }
    @Override
    protected final void onResume() {
        super.onResume();
        doResume();
    }
    @Override
    protected final void onPause() {
        doPause();
        super.onPause();
    }
    @Override
    protected final void onStop() {
        doStop();
        super.onStop();
    }
    @Override
    protected final void onStart() {
        super.onStart();
        doStart();
    }
    @Override
    protected final void onSaveInstanceState(Bundle outState) {
        doSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }
}

마지막으로,라는 활동이 AnudeepBullaActivityBaseActivity를 확장하고 나중에 SherifElKhatibActivity활동을 확장하는 것을 만들고 싶습니다 . super.do함수를 어떤 순서로 호출해야 합니까? 궁극적으로 같은 것입니다.


질문 :

Google의 의도는 다음과 같이 말하는 것 같습니다. 어디에 있든 상관없이 수퍼에 전화하십시오. 물론 일반적인 관행으로 처음에는 호출하십시오. 물론 Google에는 가장 뛰어난 엔지니어와 개발자가 있으므로 그들은 아마도 슈퍼 통화를 분리하고 어린이 통화를 방해하지 않는 좋은 작업을 수행했을 것입니다.

나는 조금 시도했지만 When is super가 호출되기 때문에 간단하게 충돌하는 활동을 만드는 것이 (Google이기 때문에 우리가 잘못 증명하고 있기 때문에) 쉽지 않을 것입니다.

왜?

이 함수에서 수행되는 모든 작업은 실제로 Activity 클래스에만 적용되며 하위 클래스와 충돌을 일으키지 않습니다. 예 : (onDestroy)

protected void onDestroy() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
    mCalled = true;

    // dismiss any dialogs we are managing.
    if (mManagedDialogs != null) {
        final int numDialogs = mManagedDialogs.size();
        for (int i = 0; i < numDialogs; i++) {
            final ManagedDialog md = mManagedDialogs.valueAt(i);
            if (md.mDialog.isShowing()) {
                md.mDialog.dismiss();
            }
        }
        mManagedDialogs = null;
    }

    // close any cursors we are managing.
    synchronized (mManagedCursors) {
        int numCursors = mManagedCursors.size();
        for (int i = 0; i < numCursors; i++) {
            ManagedCursor c = mManagedCursors.get(i);
            if (c != null) {
                c.mCursor.close();
            }
        }
        mManagedCursors.clear();
    }

    // Close any open search dialog
    if (mSearchManager != null) {
        mSearchManager.stopSearch();
    }

    getApplication().dispatchActivityDestroyed(this);
}

mManagedCursors 및 mManagedDialogs 및 mSearchManager는 모두 개인 필드입니다. 그리고 공개 / 보호 된 API는 여기서 수행되는 작업에 영향을받지 않습니다.

그러나 API 14에서는 애플리케이션에 등록 된 ActivityLifecycleCallbacks에 onActivityDestroyed를 디스패치하기 위해 dispatchActivityDestroyed가 추가되었습니다. 따라서 ActivityLifecycleCallbacks의 일부 논리에 의존하는 코드는 super를 호출하는시기에 따라 다른 결과를 갖습니다. 예를 들면 :

현재 실행중인 활동의 수를 계산하는 애플리케이션 클래스를 만듭니다.

package mobi.shush;

import android.app.Activity;
import android.app.Application;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;

public class SherifApplication extends Application implements ActivityLifecycleCallbacks {
    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(this);
    }
    public int getCount() {
        return count;
    }
    int count = 0;
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        count++;
    }
    @Override
    public void onActivityDestroyed(Activity activity) {
        count--;
    }
    @Override
    public void onActivityPaused(Activity activity) {}
    @Override
    public void onActivityResumed(Activity activity) {}
    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState)           {}
    @Override
    public void onActivityStarted(Activity activity) {}
    @Override
    public void onActivityStopped(Activity activity) {}
}

다음은 말이되지 않거나 좋은 관행이 아닐 수도 있지만 단지 요점을 증명하기위한 것입니다 (더 실제 상황을 찾을 수 있음). GoodBye 활동이 완료되고 마지막 활동 일 때 이동하는 MainActivity를 만듭니다.

@Override
protected void onDestroy() {
    super.onDestroy();
    if(((SherifApplication) getApplication()).getCount() == 0) {
        //i want to go to a certain activity when there are no other activities
        startActivity(new Intent(this, GoodBye.class));
    }
}

onDestroy를 시작할 때 super.onDestroy를 호출하면 GoodBye 활동이 시작됩니다. onDestroy가 끝날 때 super.onDestroy를 호출하면 GoodBye 활동이 시작되지 않습니다.

물론 이것은 최적의 예가 아닙니다. 그러나 이것은 Google이 여기서 약간 엉망임을 보여줍니다. 다른 변수는 앱의 동작에 영향을주지 않았습니다. 그러나 이러한 디스패치를 ​​onDestroy에 추가하면 수퍼가 어떻게 든 하위 클래스를 방해합니다.

나는 그들이 다른 이유로도 엉망이라고 말합니다. 그들은 (api 14 이전에) 최종 및 / 또는 비공개 인 슈퍼 호출 만 터치했을뿐만 아니라 실제로 onPause … 함수를 전달하는 다른 내부 함수 (비공개)를 호출했습니다.

예를 들어 performStopfunction은 onStop 함수를 차례로 호출하는 호출 된 함수입니다.

final void performStop() {
    if (mLoadersStarted) {
        mLoadersStarted = false;
        if (mLoaderManager != null) {
            if (!mChangingConfigurations) {
                mLoaderManager.doStop();
            } else {
                mLoaderManager.doRetain();
            }
        }
    }

    if (!mStopped) {
        if (mWindow != null) {
            mWindow.closeAllPanels();
        }

        if (mToken != null && mParent == null) {
            WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
        }

        mFragments.dispatchStop();

        mCalled = false;
        mInstrumentation.callActivityOnStop(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onStop()");
        }

        synchronized (mManagedCursors) {
            final int N = mManagedCursors.size();
            for (int i=0; i<N; i++) {
                ManagedCursor mc = mManagedCursors.get(i);
                if (!mc.mReleased) {
                    mc.mCursor.deactivate();
                    mc.mReleased = true;
                }
            }
        }

        mStopped = true;
    }
    mResumed = false;
}

이 함수에서 Activity의 onStop을 호출합니다. 따라서 그들은 onStop에 대한 호출 전후에 모든 코드 (super.onStop에 포함됨)를 넣은 다음 빈 onStop 슈퍼 함수를 ​​사용하고 SuperNotCalledException을 추가하거나이 호출을 확인하지 않고도 onStop에 대해 하위 클래스에 알릴 수 있습니다.

이를 위해 super.onDestroy의 끝에서 호출하는 대신 performDestroy의 ActivityLifeCycle에이 디스패치를 ​​호출하면 super를 호출 한시기에 관계없이 활동의 ​​동작이 동일했을 것입니다.

어쨌든 이것은 그들이하는 첫 번째 일이며 (약간 잘못되었습니다) API 14에만 있습니다.


답변

Google이 방법 1을 제안한다고 말하지만, 잘 알려진 Android 프레임 워크 엔지니어 인 Dianne Hackborn은 그렇지 않으면 Google Forum Link를 참조 할 것을 제안합니다 .

onPause, onStoponDestroy 메서드 에서 인스턴스를 삭제할마지막에 슈퍼 클래스를 호출하고 onCreate, onResumeonStart 메서드를 사용하여 인스턴스를 만들먼저 슈퍼 클래스를 호출하는 것이 직관적 입니다.


답변

Java 관점에서 다음은 이러한 혼란에 대한 몇 가지 해결책입니다.

왜 this ()와 super ()가 생성자의 첫 번째 문장이어야합니까?

상위 클래스의 생성자는 하위 클래스의 생성자보다 먼저 호출되어야합니다. 이렇게하면 생성자의 부모 클래스에서 메서드를 호출하는 경우 부모 클래스가 이미 올바르게 설정되었는지 확인할 수 있습니다.

당신이하려는 것은 슈퍼 생성자에 args를 전달하는 것은 완벽하게 합법적입니다. 당신이하는 것처럼 그 args를 인라인으로 생성하거나 생성자에 전달한 다음 super에 전달하기 만하면됩니다.

public MySubClassB extends MyClass {
        public MySubClassB(Object[] myArray) {
                super(myArray);
        }
}

컴파일러가 이것을 강제하지 않았다면 다음과 같이 할 수 있습니다.

public MySubClassB extends MyClass {
        public MySubClassB(Object[] myArray) {
                someMethodOnSuper(); //ERROR super not yet constructed
                super(myArray);
        }
}

실제로 서브 필드가 상위 클래스보다 먼저 비 실리 화되어야 함을 보여줍니다! 한편, 자바 요구 사항은 슈퍼 생성자 인수를 전문화하여 클래스를 전문화하는 것을 “방어”합니다.

부모 클래스에 기본 생성자가있는 경우 super에 대한 호출이 컴파일러에 의해 자동으로 삽입됩니다. Java의 모든 클래스는 Object에서 상속되기 때문에 객체 생성자는 어떻게 든 호출되어야하며 먼저 실행되어야합니다. 컴파일러에 의한 super () 자동 삽입이이를 허용합니다. super가 먼저 나타나도록 강제하면 생성자 본문이 다음과 같은 올바른 순서로 실행됩니다. Object-> Parent-> Child-> ChildOfChild-> SoOnSoForth

(1) super가 첫 번째 문장인지 확인하는 것만으로는 문제를 방지 할 수 없습니다. 예를 들어 “super (someMethodInSuper ());”를 입력 할 수 있습니다. 생성자에서. super가 첫 번째 명령문이더라도 생성되기 전에 수퍼 클래스의 메소드에 액세스하려고 시도합니다.

(2) 컴파일러는 자체적으로이 문제를 방지하기에 충분한 다른 검사를 구현하는 것으로 보입니다. 메시지는 “supertype 생성자가 호출되기 전에 xxx를 참조 할 수 없습니다”입니다. 따라서 super가 첫 번째 명령문인지 확인할 필요가 없습니다.

http://valjok.blogspot.in/2012/09/super-constructor-must-be-first.html을 살펴보십시오.


답변

명심해야 할 가장 중요한 것은 super.onPause()암시 적으로 setResult(Activity.RESULT_CANCELED). 그러나 setResult한 번만 호출 할 수 있으며 모든 후속 호출은 무시됩니다. 따라서 모든 종류의 결과를 부모 활동으로 다시 푸시하려면를 호출 하기 전에setResult 자신 에게 전화 해야 합니다 super.onPause(). 내가 아는 한 가장 큰 문제입니다.


답변

둘 다 올바른 IMO입니다.

문서에 따르면

파생 클래스는이 메서드의 슈퍼 클래스 구현을 통해 호출해야합니다. 그렇지 않으면 예외가 발생합니다.

Super 메서드는 문서에서 명시 적으로 언급 할 때 항상 호출되어야합니다.

그러나 super 메서드를 호출 할시기를 선택할 수 있습니다.

소스를 보면 onPause

protected void onPause() {
    getApplication().dispatchActivityPaused(this);
    mCalled = true;
}

따라서 호출 전후에 관계없이. 당신은 잘해야합니다.

그러나 모범 사례를 위해서는 먼저 호출해야합니다.

대부분 보호 메커니즘으로 권장합니다. 예외가 있으면 super인스턴스 메서드가 이미 호출되었을 것입니다.

또한 이러한 호출을 첫 번째 줄에 배치하면 메서드에서 코드를 삭제하고 실수로 수퍼 클래스에 대한 호출을 삭제하는 등의 실수를 방지 할 수 있습니다.


답변

콜백의 수퍼는 활동을 시스템 내부적으로 올바른 상태로 만드는 데 필요합니다.

활동을 시작하고 시스템에서 onCreate를 호출한다고 가정 해 보겠습니다. 이제이를 재정의하고 레이아웃을로드 할 수 있습니다. 그러나 시스템 흐름을 위해 super를 호출해야 시스템이 표준 절차를 계속할 수 있습니다. 이것이 호출하지 않으면 예외가 발생하는 이유입니다.

이것은 onCreate의 구현과는 별개로 발생합니다. 시스템에 대한 유일한 수입원입니다. ANR이 없으면 모든 콜백에 무한 루프가있을 수 있으며 해당 콜백에서 활동이 포착됩니다. 따라서 시스템은 콜백이 종료 된시기를 알고 다음 콜백을 호출합니다.

나는 슈퍼 콜의 타이밍이 필요한 한 가지 상황만을 알고 있습니다. onCreate에서 테마 또는 디스플레이 등의 표준 동작을 변경하려면 super를 호출하기 전에 변경해야 효과를 볼 수 있습니다. 그렇지 않으면 AFAIK를 호출하는 시간에 차이가 없습니다.

그러나 시스템이 가장 잘 할 수있는 작업을 수행 할 수 있도록하기 위해 코드가 뒤 따르는 콜백의 첫 번째 줄에 수퍼를 넣을 수 있습니다.