SuperNotCalledException Activity xxx did not call through to super.onCreate

问题

线上异常:

android.util.SuperNotCalledException: Activity {com.xxx.app/com.xxx.TestActivity} did not call through to super.onCreate()
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4037)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4247)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2613)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8668)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)

分析

看起来是派生的 Activity 中没有调用超类的 onCreate() ,也就是派生类中没有 super.onCreate() 导致的问题。追一下代码:

搜索“did not call through to super.onCreate()”:

// ActivityThread.java
/**  Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    try {
        ...
        if (activity != null) {
            ...
            // 显示的将mCalled设置为false
            activity.mCalled = false;
            // 若要不抛出下面的‘SuperNotCalledException’,只可能是callActivityOnCreate过程中对mCalled赋值为true了
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            // 检查mCalled,false的情况下就会抛出此异常
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
            mLastReportedWindowingMode.put(activity.getActivityToken(),
                    config.windowConfiguration.getWindowingMode());
        }
        ...

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }
    return activity;
}

可以看出,SuperNotCalledException 正是在 performLaunchActivity 中抛出的,而这与错误堆栈完全符合。至于从 ZygoteInit.main 到 ActivityThread.performLaunchActivity 的启动过程这里不做详细分析,我们直接从 performLaunchActivity 之后的流程分析。

既然我们已经分析出了若要正常启动Activity,就一定要在 callActivityOnCreate 过程中为 mCalled 赋值 true,那我们就继续往下追踪:

// Instrumentation.java
/**
 * Perform calling of an activity's {@link Activity#onCreate}
 * method.  The default implementation simply calls through to that method.
 *
 * @param activity The activity being created.
 * @param icicle The previously frozen state (or null) to pass through to onCreate().
 */
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    // 分别查看以下3个方法,得出对 mCalled 的赋值操作是在 activity.performCreate 过程中
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}
final void performCreate(Bundle icicle) {
    performCreate(icicle, null);
}

@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performCreate:"
                + mComponent.getClassName());
    }
    dispatchActivityPreCreated(icicle);
    mCanEnterPictureInPicture = true;
    // initialize mIsInMultiWindowMode and mIsInPictureInPictureMode before onCreate
    final int windowingMode = getResources().getConfiguration().windowConfiguration
            .getWindowingMode();
    mIsInMultiWindowMode = inMultiWindowMode(windowingMode);
    mIsInPictureInPictureMode = windowingMode == WINDOWING_MODE_PINNED;
    restoreHasCurrentPermissionRequest(icicle);
    if (persistentState != null) {
        // 双参数的 onCreate 实际上也是调用的 单参数 onCreate
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
    EventLogTags.writeWmOnCreateCalled(mIdent, getComponentName().getClassName(),
            "performCreate");
    mActivityTransitionState.readState(icicle);

    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
            com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mFragments.dispatchActivityCreated();
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    dispatchActivityPostCreated(icicle);
    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}

public void onCreate(@Nullable Bundle savedInstanceState,
        @Nullable PersistableBundle persistentState) {
    onCreate(savedInstanceState);
}

/**
 * Called when the activity is starting.  This is where most initialization
 * should go: calling {@link #setContentView(int)} to inflate the
 * activity's UI, using {@link #findViewById} to programmatically interact
 * with widgets in the UI, calling
 * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
 * cursors for data being displayed, etc.
 *
 * 

You can call {@link #finish} from within this function, in * which case onDestroy() will be immediately called after {@link #onCreate} without any of the * rest of the activity lifecycle ({@link #onStart}, {@link #onResume}, {@link #onPause}, etc) * executing. * *

Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.

* * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most * recently supplied in {@link #onSaveInstanceState}. Note: Otherwise it is null. * * @see #onStart * @see #onSaveInstanceState * @see #onRestoreInstanceState * @see #onPostCreate */ @MainThread @CallSuper protected void onCreate(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); if (mLastNonConfigurationInstances != null) { mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders); } if (mActivityInfo.parentActivityName != null) { if (mActionBar == null) { mEnableDefaultActionBarUp = true; } else { mActionBar.setDefaultDisplayHomeAsUpEnabled(true); } } if (savedInstanceState != null) { mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false); mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID, View.LAST_APP_AUTOFILL_ID); if (mAutoFillResetNeeded) { getAutofillManager().onCreate(savedInstanceState); } Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); mFragments.restoreAllState(p, mLastNonConfigurationInstances != null ? mLastNonConfigurationInstances.fragments : null); } mFragments.dispatchCreate(); dispatchActivityCreated(savedInstanceState); if (mVoiceInteractor != null) { mVoiceInteractor.attachActivity(this); } mRestoredFromBundle = savedInstanceState != null; // 这里执行完 Activity 的 onCreate 后,会修改 mCalled mCalled = true; }

至此,就确认了这个异常的触发链,不仅从整个代码的执行流程上能得到验证,从 onCreate 的另外两个地方也能看到端倪:

  • onCreate 的注解 @CallSuper:标记该方法,任何派生类若要重写该方法,则必须调用超类的方法,即 super.xxx()
// CallSuper.java
/**
 * Denotes that any overriding methods should invoke this method as well.
 * 

* Example: * *

 * 
 *  @CallSuper
 *  public abstract void onFocusLost();
 * 
 * 
* * @memberDoc If you override this method you must call through to the * superclass implementation. * @hide */ @Retention(SOURCE) @Target({METHOD}) public @interface CallSuper { }
  • onCreate 的注释也明确说明了
 * 

Derived classes must call through to the super class's *

Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.

结论

检查相应的 Activity ,确保 onCreate 中调用了 super.onCreate() 。如果不调用,IDE 会有提示,但就算不按照提示做,编译是能通过的,只是运行时,肯定就会抛出异常了。

你可能感兴趣的:(SuperNotCalledException Activity xxx did not call through to super.onCreate)