25 votes

Firebase observeSingleEvent reste en mémoire

Mon application utilise assez souvent la fonction observeSingleEventOfType de Firebase et je me suis rendu compte que la mémoire de mon application augmente avec le temps. J'ai commenté tout mon code à l'exception d'un bouton de test qui appelle la fonction suivante.

func loadPostsTest() {
    FIRDatabase.database().reference().child("posts").observeSingleEventOfType(.Value, withBlock: { (snapshot: FIRDataSnapshot) in
        print(snapshot.value)
    })
}

Lorsque le programme démarre, j'ai appuyé sur le bouton de test à une vitesse rapide environ 2,3 fois par seconde et j'ai observé le graphique de la mémoire comme indiqué ci-dessous. La mémoire augmente et ne redescend pas après la demande. Ce problème affecte mon application de manière assez importante à long terme, car la mémoire de mon application passe de 70 mb à 150+ mb à cause de cela. Quelle est la raison de ce problème ?

Notez que le court repos de cinq secondes est dû au fait que je m'arrête pour m'assurer que tous les "instantanés" sont imprimés.

Note 2... Lorsque je cesse d'appuyer sur le bouton, la mémoire reste au même niveau que celui indiqué dans la "courte section de repos". Juste au cas où vous penseriez qu'elle se développe d'elle-même indéfiniment.

memory image

-------UPDATE----------

Pour confirmer le problème, j'ai créé un tout nouveau projet avec rien d'autre que l'importation de firebase, un bouton dans le story board avec le code suivant et simulé sur mon 6s (la simulation sur simulateur ne semble pas avoir ce problème). L'image ci-dessous prouve qu'il y a quelque chose de louche avec firebase car ma mémoire est passée de 11.1mb à 17.3mb avec 303 requêtes en une minute environ.

memoryleak2

import UIKit
import Firebase

class ViewController: UIViewController {

var count: Int = 0

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

@IBAction func testBtnPressed(sender: AnyObject) {
    FIRDatabase.database().reference().child("posts").observeSingleEventOfType(.Value, withBlock: {[weak self] (snapshot: FIRDataSnapshot) in
        print(self?.count)
        self?.count += 1
    })
}

10voto

dbburgess Points 641

Il est probable que cela ne se produise que parce que vous utilisez une version de débogage. Mes résultats, après ~128 clics sur un appareil avec une version déboguée :

Increasing memory consumption after ~128 clicks on device.

Comme vous pouvez le constater, la grande majorité de la consommation de mémoire est due aux outils de performance liés au débogage. Vous pouvez désactiver cette fonctionnalité si vous souhaitez la confirmer, en modifiant votre schéma :

edit your scheme

Et ensuite, désactiver l'enregistrement du backtrace :

Disable backtrace recording.

S'il est désactivé, les mêmes ~128 clics ne montrent pratiquement aucune croissance :

No increase in memory consumption after ~128 clicks on device.

Il est vrai que vous ne voudrez peut-être pas laisser cette fonction désactivée, car elle peut être utile pour diagnostiquer les plantages et autres problèmes dans vos constructions de débogage. Cela ne devrait pas être un problème dans une version de lancement !

Pour référence, voici le code que j'exécutais :

import UIKit
import FirebaseDatabase

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    private var count: Int = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func testBtnPressed(sender: AnyObject) {
        let db = FIRDatabase.database().reference()
        db.child("posts").observeSingleEventOfType(.Value) { [weak self] (snap: FIRDataSnapshot!) in
            guard let this = self else { return }
            this.count = this.count + 1
            this.label.text = "\(this.count)"
        }
    }
}

1voto

MKJParekh Points 18108

Je pense que de cette façon, cela aidera aussi dans xcode. Je l'ai fait dans mon application Android.

DatabaseReference ref = FirebaseDatabase.getInstance().getReference("BLAH_BLAH_STRING");

            // Attach a listener to read the data at our posts reference
            ref.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    // Do Some Stuff
                    ref.removeEventListener(this);
                    ref = null;

                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                }
            });

Ou dans iOS, je suppose qu'ils ont des méthodes différentes à utiliser.

removeAllObservers y removeObserverWithHandle :

Veuillez essayer avec les deux méthodes ci-dessus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X