You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android单例初始化疑问:是否应继承Application类在onCreate中初始化?

解决单例未初始化导致的应用崩溃问题

首先明确告诉你:继承Application类并在其onCreate()中初始化单例是完全正确的做法,Android文档提到"通常无需继承Application"是因为大部分场景下确实不需要,但你的情况正好是需要继承的典型场景之一。

为什么这个方案可行?

Android应用进程启动时,系统会优先创建Application实例并调用它的onCreate()方法,这个过程发生在任何Activity、Service等组件启动之前。也就是说,不管你的应用重启后直接进入哪个Activity,单例的初始化代码都会提前执行,从根源上避免了"未初始化就调用"的崩溃问题。

具体实现步骤

  1. 创建自定义Application类:
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // 在这里完成单例的初始化,传入ApplicationContext
        MySingleton.init(applicationContext)
    }
}
  1. 在AndroidManifest.xml中配置这个自定义Application:
<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <!-- 你的Activity等组件配置 -->
</application>

替代方案:用ContentProvider初始化(无需继承Application)

如果你确实不想继承Application,还可以借助ContentProvider的特性来完成初始化——ContentProvider的onCreate()会在Application的onCreate()之前被调用,同样能保证初始化时机足够早。

实现示例:

class SingletonInitProvider : ContentProvider() {
    override fun onCreate(): Boolean {
        context?.let { ctx ->
            MySingleton.init(ctx)
        }
        return true
    }

    // 以下方法只需返回默认值即可,无需实际实现
    override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? = null
    override fun getType(uri: Uri): String? = null
    override fun insert(uri: Uri, values: ContentValues?): Uri? = null
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int = 0
}

然后在Manifest中注册这个Provider:

<provider
    android:name=".SingletonInitProvider"
    android:authorities="${applicationId}.singleton_init_provider"
    android:exported="false" />

你的崩溃原因分析

从你提供的崩溃日志可以明确看到问题:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.loser, PID: 32117 java.lang.RuntimeException: Unable to resume activity {com.loser/com.loser.Activity2}: java.lang.RuntimeException: Call init() first. at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3454) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3494) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2757) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1496) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6186) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by: java.lang.RuntimeException: Call init() first. at com.loser.MySingleton$Companion.getInstance(MySingleton.kt:44) at com.loser.Activity2.onResume(Activity2.kt:93) at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1270) at android.app.Activity.performResume(Activity.java:6788) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3431) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3494) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2757) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1496) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6186) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

当你的应用被系统后台回收后,用户再次打开时,Android会恢复之前的Activity栈,直接启动Activity2,而此时MainActivity的onCreate()并没有被执行,导致单例没有完成初始化,所以在Activity2的onResume()中调用单例时触发了Call init() first的异常。

综上,最直观且推荐的方案就是继承Application来完成单例初始化,这个方案简单易懂,也符合Android的组件生命周期规范。

内容的提问来源于stack exchange,提问作者Damn Vegetables

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:40:03