安卓Firebase实时数据库首次安装时addListenerForSingleValueEvent未触发求助
问题描述
首次安装应用时,通过Firebase Realtime Database获取数据失败,addListenerForSingleValueEvent方法未被调用;重启应用后数据可正常加载。相关代码如下:
private fun fetchData(onComplete: ((Boolean) -> Unit)?=null) { val database = FirebaseDatabase.getInstance().reference var ref: DatabaseReference? = null if (context?.packageName?.contains(".dev") == false) { ref = database.child("sticker_packs") } else { ref = database.child("sticker_packs_devs") Timber.d("it debug mode") } val phoneQuery = ref.orderByChild("identifier") val firebaseList = ArrayList<StickerPack>() phoneQuery.addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { for (singleSnapshot in dataSnapshot.children) { Timber.e(TAG, "onDataChange: ${singleSnapshot.child("stickers").value}") val stickerPacks: StickerPack? = singleSnapshot.getValue<StickerPack>() stickerspack = stickerPacks stickers = stickerPacks val unzipLocation = "${path}/${stickerPacks?.pack_id}" if (stickerPacks != null) { Timber.d("zipfilepath ${stickerPacks.zip_file}") } val tryIconPath = "$unzipLocation/try" val trypath = File(tryIconPath) val trayFile = trypath.listFiles() var tryiconImage = "" trayFile?.forEach { if (it.name.contains(".png")) { tryiconImage = it.name } Timber.d("try icon g $tryiconImage") } stickerPacks?.tray_image_file = tryiconImage val pkg = "${Package_Head}${PACKAGE_NAME}" stickerPacks?.publisherEmail = getString(R.string.feedback_email) stickerPacks?.publisherWebsite = getString(R.string.privacy_policy_link) stickerPacks?.privacyPolicyWebsite = getString(R.string.privacy_policy_link) stickerPacks?.licenseAgreementWebsite = getString(R.string.privacy_policy_link_1) stickerPacks?.isWhitelisted = true stickerPacks?.android_play_store_link = pkg if (stickerPacks != null) { firebaseList.add(stickerPacks) } } Timber.e(TAG, "onDataChangecache: ${firebaseList.size}") Timber.e(TAG, "arraylist1: ${firebaseList.size}") val getListFromMainActivity = Hawk.get("listfromactivity", ArrayList<StickerPack>()) Timber.d("CheckIfNull ${getListFromMainActivity.size}") if (getListFromMainActivity.isNullOrEmpty() && getListFromMainActivity.size <= 0) { onComplete?.invoke(false) }else{ onComplete?.invoke(true) context?.let { adapter?.setData( it, getListFromMainActivity, requireActivity(), this@StickersFragment ) } } Hawk.put("sticker_packs", firebaseList) view?.linlaHeaderProgress?.visibility = View.GONE if (view?.linlaHeaderProgress?.visibility == View.GONE) { //spinnerDialog() } Timber.e(TAG, "onDataChe0:$dataSnapshot ") } override fun onCancelled(databaseError: DatabaseError) { Timber.e(TAG, "onCancelled", databaseError.toException()) } }) } class StickerPack : Parcelable { var pack_id: String="" var pack_Name: String="" var publisher: String="" var tray_image_file: String="" var publisherEmail: String="" //exclude var publisherWebsite: String="" //exclude var privacyPolicyWebsite: String="" //exclude var licenseAgreementWebsite: String="" //exclude var iosAppStoreLink: String="" //exclude private var stickers: List<Sticker>? = null var totalSize: Long = 0 private set var android_play_store_link: String="" var isWhitelisted = false //exclude var animated_sticker_pack:Boolean= false var zip_file: String?=null }
解决方案
1. 确保Firebase在Application级别初始化
避免在Fragment/Activity中延迟初始化导致实例未就绪:
class MyApplication : Application() { override fun onCreate() { super.onCreate() FirebaseApp.initializeApp(this) } }
在AndroidManifest.xml中注册该Application:
<application android:name=".MyApplication" <!-- 其他配置 --> > </application>
2. 校验fetchData调用时机
确保在context完全可用后调用该方法:
- 如果是Fragment,在
onViewCreated或onResume中调用 - 如果是Activity,在
onStart或onResume中调用
3. 增加ref非空判断与数据同步
避免因context为空导致ref未初始化,同时强制同步数据确保首次安装时能从网络获取:
private fun fetchData(onComplete: ((Boolean) -> Unit)?=null) { val database = FirebaseDatabase.getInstance().reference val ref = if (context?.packageName?.contains(".dev") == false) { database.child("sticker_packs") } else { database.child("sticker_packs_devs").also { Timber.d("it debug mode") } } // 新增非空判断,避免空指针 if (ref == null) { Timber.e(TAG, "Database reference is null, context might be unavailable") onComplete?.invoke(false) view?.linlaHeaderProgress?.visibility = View.GONE return } val phoneQuery = ref.orderByChild("identifier") // 强制同步数据,确保首次安装时能从网络获取 phoneQuery.keepSynced(true) val firebaseList = ArrayList<StickerPack>() // 剩余代码保持不变 }
4. 排查数据库规则与网络权限
- 确认Firebase Realtime Database的读写规则允许当前应用访问(首次安装时若规则限制,
onCancelled会触发,可查看日志) - 检查应用是否已声明
INTERNET权限:
<uses-permission android:name="android.permission.INTERNET" />
5. 优化onDataChange逻辑
首次安装时Hawk.get("listfromactivity")必然为空,应直接使用从Firebase获取的firebaseList:
// 替换原判断逻辑 if (firebaseList.isEmpty()) { onComplete?.invoke(false) } else { onComplete?.invoke(true) context?.let { adapter?.setData(it, firebaseList, requireActivity(), this@StickersFragment) } } Hawk.put("sticker_packs", firebaseList) // 同时更新Hawk中的"listfromactivity",避免后续依赖旧数据 Hawk.put("listfromactivity", firebaseList)
内容的提问来源于stack exchange,提问作者user19499909
相关产品推荐
相关产品推荐

