Kotlin安卓Instagram克隆应用崩溃:ExceptionInInitializerError求助
问题描述
从GitHub克隆了Kotlin版本的Instagram克隆应用,修改代码后应用启动即崩溃,抛出java.lang.ExceptionInInitializerError异常,根源错误为:
Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.example.instagramclone. Make sure to call FirebaseApp.initializeApp(Context) first.
已在自定义Application类InstagramApp的onCreate方法中添加FirebaseApp.initializeApp(this)初始化代码,但问题仍未解决。以下是相关代码片段及完整报错信息:
Manifest.xml
<application android:name=".screens.InstagramApp" ....> <activity android:name=".screens.home.HomeActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ...... </application>
InstagramApp.kt
class InstagramApp : Application() { val usersRepo by lazy { FirebaseUsersRepository() } val feedPostsRepo by lazy { FirebaseFeedPostsRepository() } val notificationsRepo by lazy { FirebaseNotificationsRepository() } val authManager by lazy { FirebaseAuthManager() } val searchRepo by lazy { FirebaseSearchRepository() } override fun onCreate() { super.onCreate() FirebaseApp.initializeApp(this) NotificationsCreator(notificationsRepo, usersRepo, feedPostsRepo) SearchPostsCreator(searchRepo) } }
HomeActivity.kt
class HomeActivity : BaseActivity(), FeedAdapter.Listener { private lateinit var mAdapter: FeedAdapter private lateinit var mViewModel: HomeViewModel @SuppressLint("CutPasteId") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_home) Log.d(TAG, "onCreate") mAdapter = FeedAdapter(this) findViewById<RecyclerView>(R.id.feed_recycler).adapter = mAdapter findViewById<RecyclerView>(R.id.feed_recycler).layoutManager = LinearLayoutManager(this) setupAuthGuard { uid -> setupBottomNavigation(uid, 0) mViewModel = initViewModel() mViewModel.init(uid) mViewModel.feedPosts.observe(this, Observer { it?.let { mAdapter.updatePosts(it) } }) mViewModel.goToCommentsScreen.observe(this, Observer { it?.let { postId -> CommentsActivity.start(this, postId) } }) } } override fun toggleLike(postId: String) { Log.d(TAG, "toggleLike: $postId") mViewModel.toggleLike(postId) } override fun loadLikes(postId: String, position: Int) { if (mViewModel.getLikes(postId) == null) { mViewModel.loadLikes(postId).observe(this, Observer { it?.let { postLikes -> mAdapter.updatePostLikes(position, postLikes) } }) } } override fun openComments(postId: String) { mViewModel.openComments(postId) } companion object { const val TAG = "HomeActivity" } }
AuthGuard.kt
class AuthGuard(private val activity: BaseActivity, f: (String) -> Unit) : LifecycleObserver { init { if (auth.currentUser == null) { activity.goToLogin() } else { f(auth.currentUser!!.uid) activity.lifecycle.addObserver(this) } } private val listener = FirebaseAuth.AuthStateListener { if (it.currentUser == null) { activity.goToLogin() } } @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onStart() { auth.addAuthStateListener(listener) } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onStop() { auth.removeAuthStateListener(listener) } } fun BaseActivity.setupAuthGuard(f: (String) -> Unit) { AuthGuard(this, f) }
FirebaseUtils.kt
val auth: FirebaseAuth = FirebaseAuth.getInstance() val database: DatabaseReference = FirebaseDatabase.getInstance().reference val storage: StorageReference = FirebaseStorage.getInstance().reference fun DatabaseReference.liveData(): LiveData<DataSnapshot> = FirebaseLiveData(this)
完整报错栈
AndroidRuntime com.example.instagramclone E FATAL EXCEPTION: main Process: com.example.instagramclone, PID: 7526 java.lang.ExceptionInInitializerError at com.example.instagramclone.screens.common.AuthGuard.<init>(AuthGuard.kt:12) at com.example.instagramclone.screens.common.AuthGuardKt.setupAuthGuard(AuthGuard.kt:38) at com.example.instagramclone.screens.home.HomeActivity.onCreate(HomeActivity.kt:33) at android.app.Activity.performCreate(Activity.java:8595) at android.app.Activity.performCreate(Activity.java:8573) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.example.instagramclone. Make sure to call FirebaseApp.initializeApp(Context) first. at com.google.firebase.FirebaseApp.getInstance(FirebaseApp.java:179) at com.google.firebase.auth.FirebaseAuth.getInstance(com.google.firebase:firebase-auth@@23.0.0:283) at com.example.instagramclone.data.firebase.common.FirebaseUtilsKt.<clinit>(FirebaseUtils.kt:11) at com.example.instagramclone.screens.common.AuthGuard.<init>(AuthGuard.kt:12) at com.example.instagramclone.screens.common.AuthGuardKt.setupAuthGuard(AuthGuard.kt:38) at com.example.instagramclone.screens.home.HomeActivity.onCreate(HomeActivity.kt:33) at android.app.Activity.performCreate(Activity.java:8595) at android.app.Activity.performCreate(Activity.java:8573) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
解决方案
问题出在FirebaseUtils.kt中的全局变量初始化时机过早:Kotlin的顶级属性会在类加载阶段就完成初始化,而此时Application的onCreate方法还未执行,FirebaseApp尚未完成初始化,调用FirebaseAuth.getInstance()就会触发异常。
修复步骤:
- 修改FirebaseUtils.kt,将全局变量改为
lazy初始化,延迟到第一次使用时才获取实例:
val auth: FirebaseAuth by lazy { FirebaseAuth.getInstance() } val database: DatabaseReference by lazy { FirebaseDatabase.getInstance().reference } val storage: StorageReference by lazy { FirebaseStorage.getInstance().reference } fun DatabaseReference.liveData(): LiveData<DataSnapshot> = FirebaseLiveData(this)
- (可选)移除
InstagramApp中手动添加的FirebaseApp.initializeApp(this),因为Firebase SDK会自动在Application启动时完成初始化,手动调用可能导致重复初始化问题(前提是你的google-services.json配置正确)。
原理说明
lazy初始化保证了Firebase实例只会在第一次被调用时才会去获取,此时Application的onCreate已经执行完毕,FirebaseApp已经完成初始化,不会再触发未初始化的异常。
内容的提问来源于stack exchange,提问作者Prasad B
相关产品推荐
相关产品推荐

