J'ai un tableau de clés qui mènent à publier des objets pour mon réseau social comme so / posts / id / (post info)
Lorsque je charge les messages, je charge / posts / 0 puis / posts / 1 etc. en utilisant la observeSingleEventOfType(.Value)
méthode.
J'utilise un lazyTableView
pour charger 30 à la fois et c'est assez lent. Est-il possible d'utiliser l'une des méthodes de requête ou un autre moyen de l'accélérer même si je dois restructurer les données dans mon arbre JSON.
Je viens de Parse réimplémentant mon application et jusqu'à présent, l'expérience a été plutôt bonne. Juste cette chose sur laquelle je suis un peu coincé. Merci d'avance pour l'aide!
ÉDITER:
func loadNext(i: Int) {
// check if exhists
let ideaPostsRef = Firebase(url: "https://APPURL")
ideaPostsRef.childByAppendingPath(i.description).observeSingleEventOfType(.Value, withBlock: {
(snapshot) in
if i % 29 == 0 && i != 0 && !self.hitNull { return }
// false if nil
// true if not nil
if !(snapshot.value is NSNull) {
let postJSON = snapshot.value as! [String: AnyObject]
print("GOT VALID \(postJSON)")
let post = IdeaPost(message: postJSON["message"] as! String, byUser: postJSON["user"] as! String, withId: i.description)
post.upvotes = postJSON["upvotes"] as! Int
self.ideaPostDataSource.append(post)
self.loadNext(i + 1)
} else {
// doesn't exhist
print("GOT NULL RETURNING AT \(i)")
self.doneLoading = true
self.hitNull = true
return
}
}
}
Cette fonction récursive exécute essentiellement l'obtention de la valeur du numéro de clé i à partir de Firebase. Si c'est NSNULL, il sait que c'est la dernière publication possible à charger et ne le fait plus jamais. Si NSNULL n'est pas atteint, mais i % 29 == 0
il retourne comme cas de base, donc seuls 30 messages sont chargés à la fois (0 indexé). Lorsque je définis doneLoading
sur true
, tableView.reloadData()
est appelé à l'aide d'un observateur de propriété.
Voici un exemple de ce à quoi ressemble le tableau que je récupère
"ideaPosts" : [ {
"id" : 0,
"message" : "Test",
"upvotes" : 1,
"user" : "Anonymous"
}, {
"id" : 1,
"message" : "Test2",
"upvotes" : 1,
"user" : "Anonymous"
} ]
Réponses:
Mise à jour: nous couvrons désormais également cette question dans un épisode AskFirebase .
Le chargement de nombreux éléments depuis Firebase ne doit pas nécessairement être lent, car vous pouvez canaliser les requêtes. Mais votre code rend cela impossible, ce qui entraînera en effet des performances sous-optimales.
Dans votre code, vous demandez un élément au serveur, attendez le retour de cet élément, puis chargez le suivant. Dans un diagramme de séquence simplifié qui ressemble à:
Dans ce scénario, vous attendez 30 fois votre temps aller-retour + 30 fois le temps nécessaire pour charger les données à partir du disque. Si (par souci de simplicité) nous disons que les allers-retours prennent 1 seconde et que le chargement d'un élément à partir du disque prend également une seconde au moins à 30 * (1 + 1) = 60 secondes.
Dans les applications Firebase, vous obtiendrez de bien meilleures performances si vous envoyez toutes les demandes (ou au moins un nombre raisonnable d'entre elles) en une seule fois:
Si nous supposons à nouveau un aller-retour d'1 seconde et 1 seconde de chargement, vous attendez 30 * 1 + 1 = 31 secondes.
Donc: toutes les demandes passent par la même connexion. Étant donné que, la seule différence entre
get(1)
,get(2)
,get(3)
etgetAll([1,2,3])
est une surcharge pour les cadres.J'ai mis en place un jsbin pour démontrer le comportement . Le modèle de données est très simple, mais il montre la différence.
À titre de comparaison: le chargement séquentiel de 64 éléments prend 3,8 secondes sur mon système, tandis que leur chargement en pipeline (comme le client Firebase le fait en natif) prend 600 ms. Les chiffres exacts dépendront de votre connexion (latence et bande passante), mais la version en pipeline devrait toujours être beaucoup plus rapide.
la source