J'ai créé un ListView rempli par les données renvoyées par une requête.
Cela fonctionne, mais dans LogCat j'ai le message:
Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes
et il utilise quelques minutes pour charger/visualiser le ListView.
Ma requête renvoie environ 3700 lignes de String/Int/Double, chacune avec 30 colonnes; pas d'images ou de types de données particuliers
Que signifie exactement ce message et comment puis-je l'éviter?
Pouvez-vous améliorer les performances en modifiant cette fenêtre de curseur?
D'après mon expérience, cela signifie que les résultats de la requête sont trop grands pour la fenêtre du curseur et qu'il demande plus de mémoire. La plupart du temps, cette demande est honorée, mais sur les appareils bas de gamme, elle peut lever des exceptions.
Je ne connais pas les détails de l'application en question, mais vous avez fait référence à un ListView. Un ListView ne peut pas afficher 3700 lignes à la fois et un liste sans fin pourrait aider à charger les données à la demande
Mon conseil est de diviser la requête en plusieurs requêtes qui retournent des résultats plus petits et de les fermer avant d'exécuter la requête suivante. Après chaque requête successive, combinez les résultats.
Version courte:
Après une enquête, il apparaît que ce message fait partie du fonctionnement normal et n'est pas une source de préoccupation. Il est enregistré au niveau "Avertissement", mais je pense que c'est tout simplement exagéré.
Version plus longue:
Il s'agit (clairement étiqueté comme) d'un curseur "fenêtré", ce qui signifie que les anciens enregistrements seront supprimés à mesure que de nouveaux enregistrements sont obtenus. Dans la forme la plus simple, une telle implémentation de "fenêtre" peut contenir jusqu'à N lignes au total, éventuellement avec une lecture anticipée. Dans cette implémentation, cependant, la taille de la fenêtre est définie à la place par la taille totale. Le nombre de lignes conservées en mémoire est plutôt basé sur le nombre de lignes qui pourraient tenir dans la fenêtre globale, et variera au moment de l'exécution (cela pourrait peut-être être considéré plus comme un curseur "tamponné" que comme un curseur "fenêtré").
En tant qu'implémentation tamponnée avec une taille limitée (douce -?), Les premières lignes ne seront supprimées que lorsque le tampon est trop plein pour accueillir la ligne suivante. Dans ce cas, une ou plusieurs lignes plus anciennes sont supprimées. Ce processus "continue d'allouer les lignes selon les besoins jusqu'à ce que nous ne puissions plus en avoir plus, auquel cas nous libérons les enregistrements les plus anciens dans notre mémoire tampon et réessayons". Le processus semble être tout à fait normal et attendu, en tant que partie normale du processus pour garder l'espace mémoire confiné.
J'ai basé cette conclusion sur la lecture de la source ici, combinée à une inférence: https://Android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/CursorWindow.cpp
Pourquoi les gens parlent-ils d'images et d'autres LOB massifs?
Si la taille d'une seule ligne est supérieure à l'ensemble de la "fenêtre" (tampon), cette stratégie tombe en panne et vous avez un problème réel.
C'était le message que @op recevait:
Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes
C'était le message que @vovahost recevait:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes
Dans le premier cas, l'allocation demandée est beaucoup plus petite que la taille des fenêtres. Je m'attends à ce que des messages similaires soient émis à plusieurs reprises, avec la même taille de fenêtre et différentes tailles d'allocation demandées. À chaque impression, la mémoire est libérée de la plus grande fenêtre et de nouvelles allocations sont effectuées. Il s'agit d'un fonctionnement normal et sain.
Dans le deuxième cas, la taille d'allocation demandée dépasse la taille globale de la fenêtre. Il s'agit d'un problème réel, nécessitant le stockage et la lecture des données de manière plus fluide.
La différence est la "longueur" (nombre total de lignes) par rapport à la "largeur" (coût de la mémoire de la plus grande ligne unique). Le premier (problème de @ tirrel) n'est pas un problème, mais le second (problème de @ vovahost) l'est.
J'ai aussi eu ce problème. Dans mon cas, j'ai enregistré une image de 2,2 Mo dans la base de données. Lors du chargement des données de la base de données à l'aide de Cursor.getBlob()
je verrais ce message dans le journal:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes
Après avoir obtenu ce message si j'essaie de récupérer des données (chaîne, nombre, etc.) pour les lignes successives, il est renvoyé sous la forme null sans aucune erreur. La solution consistait à supprimer le blob de 2,2 Mo. Je ne sais pas s'il est possible de charger de plus gros blobs à partir d'une base de données dans Android.