SuperNotCalledException Activity xxx did not call through to super.onCreate

问题

线上异常:

android.util.SuperNotCalledException: Activity {com.xxx.app/com.xxx.TestpActivity} 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.
 *
 * <p>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.
 *
 * <p><em>Derived classes must call through to the super class's
 * implementation of this method.  If they do not, an exception will be
 * thrown.</em></p>
 *
 * @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}.  <b><i>Note: Otherwise it is null.</i></b>
 *
 * @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.
 * <p>
 * Example:
 *
 * <pre>
 * <code>
 *  &#64;CallSuper
 *  public abstract void onFocusLost();
 * </code>
 * </pre>
 *
 * @memberDoc If you override this method you <em>must</em> call through to the
 *            superclass implementation.
 * @hide
 */
@Retention(SOURCE)
@Target({METHOD})
public @interface CallSuper {
}
  • onCreate 的注释也明确说明了
 * <p><em>Derived classes must call through to the super class's
 * <p><em>Derived classes must call through to the super class's
 * implementation of this method.  If they do not, an exception will be
 * thrown.</em></p>

结论

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未子涵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值