- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我会尽力解释我在做什么。我有一个无限滚动的 Collection View ,它从我的 firebase 数据库中为每个单元格加载一个值。每次 Collection View 创建一个单元格时,它都会在数据库位置调用 .observe 并获取一个 snapchat。如果它加载任何值,它会将单元格背景设置为黑色。黑色背景 = 从数据库加载的单元格。如果您查看下图,您会发现并非所有单元格都从数据库中加载。数据库不能处理这么多调用吗?是线程问题吗?我正在做的事情是否适用于 Firebase?截至目前,我在我的覆盖 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {方法
经过一些测试后,它似乎可以很好地从 firebase 加载所有内容,但不会更新 UI。这让我相信它会在出于某种原因加载信息之前创建单元格?我将尝试弄清楚如何以某种方式使其“阻塞”。
最佳答案
您应该将加载委托(delegate)给单元格本身,而不是您的 collectionView: cellForItemAtIndexPath 方法。这样做的原因是委托(delegate)方法将异步挂起并用于 FireBase 网络任务的回调。虽然后者通常很快(根据经验),但您可能会在此处加载 UI 时遇到一些问题。根据 View 中的方 block 数量来判断。
理想情况下,你会想要这样的东西:
import FirebaseDatabase
class FirebaseNode {
//This allows you to set a single point of reference for Firebase Database accross your app
static let ref = Database.database().reference(fromURL: "Your Firebase URL")
}
class BasicCell : UICollectionViewCell {
var firPathObserver : String { //This will make sure that as soon as you set the value, it will fetch from firebase
didSet {
let path = firPathObserver
FirebaseNode.ref.thePathToYouDoc(path) ..... {
snapshot _
self.handleSnapshot(snapshot)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupSubViews()
}
func setupSubViews() {
//you add your views here..
}
func handleSnapshot(_ snapshot: FIRSnapshot) {
//use the content of the observed value
DispatchQueue.main.async {
//handle UI updates/animations here
}
}
}
你会使用它:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let path = someWhereThatStoresThePath(indexPath.item)//you get your observer ID according to indexPath.item.. in whichever way you do this
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Your Cell ID", for: indexPath) as! BasicCell
cell.firPathObserver = path
return cell
}
如果这不起作用,则可能是您遇到了一些 Firebase 限制……在我看来这不太可能。
通过一些更正和本地缓存更新 ..。
class FirebaseNode {
//This allows you to set a single point of reference for Firebase Database accross your app
static let node = FirebaseNode()
let ref = Database.database().reference(fromURL: "Your Firebase URL")
//This is the cache, set to private, since type casting between String and NSString would add messiness to your code
private var cache2 = NSCache<NSString, DataSnapshot>()
func getSnapshotWith(_ id: String) -> DataSnapshot? {
let identifier = id as NSString
return cache2.object(forKey: identifier)
}
func addSnapToCache(_ id: String,_ snapshot: DataSnapshot) {
cache2.setObject(snapshot, forKey: id as NSString)
}
}
class BasicCell : UICollectionViewCell {
var firPathObserver : String? { //This will make sure that as soon as you set the value, it will fetch from firebase
didSet {
handleFirebaseContent(self.firPathObserver)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupSubViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupSubViews() {
//you add your views here..
}
func handleFirebaseContent(_ atPath: String?) {
guard let path = atPath else {
//there is no content
handleNoPath()
return
}
if let localSnap = FirebaseNode.node.getSnapshotWith(path) {
handleSnapshot(localSnap)
return
}
makeFirebaseNetworkTaskFor(path)
}
func handleSnapshot(_ snapshot: DataSnapshot) {
//use the content of the observed value, create and apply vars
DispatchQueue.main.async {
//handle UI updates/animations here
}
}
private func handleNoPath() {
//make the change.
}
private func makeFirebaseNetworkTaskFor(_ id: String) {
FirebaseNode.node.ref.child("go all the way to your object tree...").child(id).observeSingleEvent(of: .value, with: {
(snapshot) in
//Add the conditional logic here..
//If snapshot != "<null>"
FirebaseNode.node.addSnapToCache(id, snapshot)
self.handleSnapshot(snapshot)
//If snapshot == "<null>"
return
}, withCancel: nil)
}
}
但有一点,使用 NSCache:这对于中小型列表或内容范围非常有效;但它具有内存管理功能,可以在内存变得稀缺时取消分配内容。因此,在处理像您这样的大型集合时,您不妨使用分类字典,因为它的内存不会自动取消分配。使用它就像交换东西一样简单:
class FirebaseNode {
//This allows you to set a single point of reference for Firebase Database accross your app
static let node = FirebaseNode()
let ref = Database.database().reference(fromURL: "Your Firebase URL")
//This is the cache, set to private, since type casting between String and NSString would add messiness to your code
private var cache2 : [String:DataSnapshot] = [:]
func getSnapshotWith(_ id: String) -> DataSnapshot? {
return cache2[id]
}
func addSnapToCache(_ id: String,_ snapshot: DataSnapshot) {
cache2[id] = snapshot
}
}
此外,始终确保您通过 node
对 Firebasenode
的强引用,这确保您始终使用 Firebasenode
。也就是说,这是可以的:
Firebasenode.node.ref
或 Firebasenode.node.getSnapshot..
,这不是:Firebasenode.ref
或 Firebasenode().ref
关于ios - 如何正确加载来自 Firebase 的信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45427218/
这个问题已经有答案了: How to do case insensitive string comparison? (23 个回答) 已关闭 3 年前。 用户在我的输入栏中写入“足球”,然后执行第 6
啊,不习惯 javascript 中的字符串。 character_id= + id + correct= + correctOrIncorrect 这就是我需要制作成字符串的内容。如果您无法猜测字符
$(function() { var base_price = 0; CalculatePrice(); $(".math1").on('change', function(e) { Calc
我找不到任何文章回答问题:将Spinnaker部署到Spinnaker将管理的同一Kubernetes集群是否安全/正确?我主要是指生产,HA部署。 最佳答案 我认为Spinnaker和Kuberne
我正在使用MSVC在Windows上从源代码(官方源代码发布,而不是从仓库中)构建Qt5(Qt 5.15.0)。 我正在设置环境。变量,依赖项等,然后运行具有1600万个选项的configure,最后
我需要打印一个包含重复单词的数组。我的数组已经可以工作,但我不知道如何正确计算单词数。我已经知道,当我的索引计数器 (i) 为 49 时,并且当 (i) 想要计数到 50 时,我会收到错误,但我不知道
我正在遵循一个指南,该指南允许 Google map 屏幕根据屏幕尺寸禁用滚动。我唯一挣扎的部分是编写一个代码,当我手动调整屏幕大小时动态更改 True/False 值。 这是我按照说明操作的网站,但
我有一个类“FileButton”。它的目的是将文件链接到 JButton,FileButton 继承自 JButton。子类继承自此以使用链接到按钮的文件做有用的事情。 JingleCardButt
我的 friend 数组只返回一个数字而不是所有数字。 ($myfriends = 3) 应该是…… ($myfriends = 3 5 7 8 9 12). 如果我让它进入 while 循环……整个
这个问题在这里已经有了答案: Is there a workaround to make CSS classes with names that start with numbers valid?
我正在制作一个 JavaScript 函数,当调整窗口大小时,它会自动将 div 的大小调整为与窗口相同的宽度/高度。 该功能非常基本,但我注意到在调整窗口大小时出现明显的“绘制”滞后。在 JS fi
此问题的基本视觉效果可在 http://sevenx.de/demo/bootstrap-carousel/inc.carousel/tabbed-slider.html 获得。 - 如果你想看一看。
我明白,如果我想从函数返回一个字符串文字或一个数组,我应该将其声明为静态的,这样当被调用的函数被返回时,内容就不会“消亡”。 但我的问题是,当我在函数内部使用 malloc 分配内存时会怎样? 在下面
在 mySQL 数据库中存储 true/false/1/0 值最合适(读取数据消耗最少)的数据字段是什么? 我以前使用过一个字符长的 tinyint,但我不确定它是否是最佳解决方案? 谢谢! 最佳答案
我想一次读取并处理CSV文件第一行中的条目(例如打印)。我假设使用Unix风格的\n换行符,没有条目长度超过255个字符,并且(现在)在EOF之前有一个换行符。这意味着它是fgets()后跟strto
所以,我们都知道 -1 > 2u == true 的 C/C++ 有符号/无符号比较规则,并且我有一种情况,我想有效地实现“正确”比较。 我的问题是,考虑到人们熟悉的尽可能多的架构,哪种方法更有效。显
**摘要:**文章的标题看似自相矛盾。 本文分享自华为云社区《Java异常处理:如何写出“正确”但被编译器认为有语法错误的程序》,作者: Jerry Wang 。 文章的标题看似自相矛盾,然而我在“正
我有一个数据框,看起来像: dataDemo % mutate_each(funs(ifelse(. == '.', REF, as.character(.))), -POS) # POS REF
有人可以帮助我使用 VBScript 重新格式化/正确格式化带分隔符的文本文件吗? 我有一个文本文件 ^分界如下: AGREE^NAME^ADD1^ADD2^ADD3^ADD4^PCODE^BAL^A
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!