Android聊天Activity销毁重启后出现白屏问题求助
问题
我的应用中Chat Activity在销毁后(未关闭应用)重新启动时,会显示1-2秒的白屏。尝试在应用主题中添加<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>未生效,将init()函数移至后台线程也没有解决问题。以下是onCreate()和onStart()方法代码,需要优化启动性能:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityChatBinding.inflate(layoutInflater) setContentView(binding.root) when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) { Configuration.UI_MODE_NIGHT_YES -> {} Configuration.UI_MODE_NIGHT_NO -> {} } //setSupportActionBar(chatToolbar) init() Handler().postDelayed({ init() }, 10) audioRecordView = AudioRecordView() audioRecordView.initView(findViewById<View>(R.id.layoutMain) as FrameLayout) val containerView = audioRecordView.setContainerView(R.layout.layout_chatting) record = layoutInflater.inflate(R.layout.record_view, null) audioRecordView.recordingListener = this uName = containerView?.findViewById(R.id.chatUserName)!! uImage = containerView.findViewById(R.id.chatUserImg)!! uPresence = containerView.findViewById(R.id.chatUserPresence) recyclerView = containerView.findViewById(R.id.recyclerViewMessages) addContacts() EmojiManager.install( GoogleCompatEmojiProvider( EmojiCompat.init( FontRequestEmojiCompatConfig( this, FontRequest( "com.google.android.gms.fonts", "com.google.android.gms", "Noto Color Emoji Compat", R.array.com_google_android_gms_fonts_certs, ) ).setReplaceAll(true) ) ) ) //EmojiManager.install(FacebookEmojiProvider()) //EmojiManager.install(TwitterEmojiProvider()) val rootView = findViewById<View>(R.id.layoutMain) emojiPopup = EmojiPopup(rootView, audioRecordView.messageView!!) if (emojiPopup.isShowing){ audioRecordView.emojiView?.setImageResource(R.drawable.ic_keyboard) } else { audioRecordView.emojiView?.setImageResource(R.drawable.emoji_ic) } //Record val filePath:String = externalCacheDir?.absolutePath + "/audioFile.wav" waveRecorder = WaveRecorder(filePath) waveRecorder.onStateChangeListener = { when (it) { RecorderState.RECORDING -> startRecording() RecorderState.STOP -> stopRecording() RecorderState.PAUSE -> pauseRecording() } } waveRecorder.onTimeElapsed = { Log.e(TAG, "onCreate: time elapsed $it") } //Chat messages = ArrayList() senderRoom = senderUid+receiverUid receiverRoom = receiverUid+senderUid setTxtDataToAdapter() //setImgDataToAdapter() setRecyclerView() //setListeners() setListener() //audioRecordView.messageView!!.requestFocus() val profileL = containerView.findViewById<View>(R.id.userImgNameL) val backBtn = containerView.findViewById<View>(R.id.single_ChatBack) profileL?.setOnClickListener{} backBtn?.setOnClickListener{ finish() } audioRecordView.setAttachmentOptions(AttachmentOption.defaultList, this) audioRecordView.removeAttachmentOptionAnimation(false) audioRecordView.removeAttachmentOptionAnimation(false) }
override fun onStart() { super.onStart() val currentId = FirebaseAuth.getInstance().uid val presence = hashMapOf<String, Any>("presence" to "Online") val state = hashMapOf<String, Any>("state" to "available") firestore.collection("Users").document(currentId!!).update(presence) firestore.collection("Contacts").document(userId).collection("rooms") .document(currentId).update(state) val seen = hashMapOf<String, Any>("seen" to "true") firestore.collection("Chats").document(senderRoom!!) .collection("messages").document().update(seen) firestore.collection("Chats").document(receiverRoom!!) .collection("messages").document().update(seen) }
优化方案
1. 移除重复初始化操作
代码中init()被重复调用两次,直接删除延迟调用的冗余代码:
// 删除这段重复初始化代码 Handler().postDelayed({ init() }, 10)
2. 异步初始化EmojiCompat
EmojiCompat初始化涉及字体加载,属于耗时操作,必须放到后台线程执行,避免阻塞主线程:
// 替换原EmojiManager初始化代码 lifecycleScope.launch(Dispatchers.IO) { val config = FontRequestEmojiCompatConfig( this@ChatActivity, FontRequest( "com.google.android.gms.fonts", "com.google.android.gms", "Noto Color Emoji Compat", R.array.com_google_android_gms_fonts_certs, ) ).setReplaceAll(true) EmojiCompat.init(config) EmojiManager.install(GoogleCompatEmojiProvider(EmojiCompat.get())) // 初始化完成后若需更新UI,切换回主线程 withContext(Dispatchers.Main) { updateEmojiButtonState() } }
3. 优化视图查找与布局加载
- 利用已有的
ActivityChatBinding替代findViewById,减少视图查找耗时; - 延迟加载非核心视图(如录音面板),等到需要使用时再初始化:
// 移除onCreate中的record初始化代码,改为在startRecording中加载 private fun startRecording() { if (record == null) { record = layoutInflater.inflate(R.layout.record_view, null) // 绑定录音面板的视图逻辑 } // 原有录音启动逻辑 }
4. 合并Firestore批量更新
onStart中的多次Firestore操作可合并为批量写,减少网络请求次数:
override fun onStart() { super.onStart() val currentId = FirebaseAuth.getInstance().uid ?: return val batch = firestore.batch() // 更新在线状态 batch.update(firestore.collection("Users").document(currentId), mapOf("presence" to "Online")) batch.update(firestore.collection("Contacts").document(userId).collection("rooms").document(currentId), mapOf("state" to "available")) // 批量更新消息已读状态(修正原代码空文档更新的问题) firestore.collection("Chats").document(senderRoom!!).collection("messages") .whereEqualTo("seen", false) .get() .addOnSuccessListener { snapshot -> snapshot.documents.forEach { doc -> batch.update(doc.reference, mapOf("seen" to true)) } firestore.collection("Chats").document(receiverRoom!!).collection("messages") .whereEqualTo("seen", false) .get() .addOnSuccessListener { receiverSnapshot -> receiverSnapshot.documents.forEach { doc -> batch.update(doc.reference, mapOf("seen" to true)) } batch.commit() } } }
5. 解决启动白屏问题
白屏源于Activity启动时窗口背景未设置,修改Chat Activity专属主题:
<!-- styles.xml中定义主题 --> <style name="Theme.ChatActivity" parent="Theme.AppCompat.Light.NoActionBar"> <!-- 设置与聊天界面匹配的窗口背景 --> <item name="android:windowBackground">@color/colorPrimary</item> <item name="android:statusBarColor">?attr/colorPrimaryVariant</item> </style>
在AndroidManifest.xml中为Chat Activity指定该主题:
<activity android:name=".ChatActivity" android:theme="@style/Theme.ChatActivity"/>
6. 延迟非核心初始化
将WaveRecorder、EmojiPopup等非立即需要的初始化移至onResume,减少onCreate执行时间:
override fun onResume() { super.onResume() // 初始化WaveRecorder if (waveRecorder == null) { val filePath: String = externalCacheDir?.absolutePath + "/audioFile.wav" waveRecorder = WaveRecorder(filePath) waveRecorder.onStateChangeListener = { when (it) { RecorderState.RECORDING -> startRecording() RecorderState.STOP -> stopRecording() RecorderState.PAUSE -> pauseRecording() } } waveRecorder.onTimeElapsed = { Log.e(TAG, "onResume: time elapsed $it") } } // 初始化EmojiPopup if (emojiPopup == null && audioRecordView.messageView != null) { val rootView = binding.layoutMain emojiPopup = EmojiPopup(rootView, audioRecordView.messageView!!) updateEmojiButtonState() } } // 提取表情按钮状态更新为单独方法 private fun updateEmojiButtonState() { audioRecordView.emojiView?.setImageResource( if (emojiPopup?.isShowing == true) R.drawable.ic_keyboard else R.drawable.emoji_ic ) }
内容的提问来源于stack exchange,提问作者Mahmoud Nabil
相关产品推荐
相关产品推荐

