Pb avec getSharedPreferences

Bonjour,
Je suis le cours avec la création d’un bloc notes. Je pense avoir respecté les règles mais j’ai une erreur pour récupérer le texte avec getSharedPreferences.
J’ai une erreur dans : textInitial = memout.getString(« memoire »,"") dès que j’écris la valeur par défaut …

memout.getString("memoire","") te renvoie un optionnel String? et ta variable a été initialisée en String (avec ton = «  ») donc ça ne fonctionne pas.
Soit tu initialises ta variable en String?, soit tu fais un test pour être sûr de ne pas avoir de null, soit du fais un elvis operator (si tu vois ce que c’est :slight_smile:)

Merci pour ce retour rapide schtipoun,
J’ai compris la source de l’erreur. J’ai modifié en reproduisant le cours sur le Bloc Note (voir ci dessous). J’ai ajouté le « if else » mais l’erreur est toujours là !


PS : je ne vois pas du tout ce qu’est un elvis operator

J’ai un problème similaire à celui d’AtomicBomb, c’est pourquoi je me permets de poster ici.

je rencontre un soucis pour récupérer le texte getSharedPreferences

Est-ce que ça pourrait être la valeur " " (vide) insérée après la clé ?

@ Schtipoun : ça consiste en quoi "initialiser la variable en String? " stp ?

Edit : j’ai réglé mon problème en ajoutant [ .toString () ] en fin de ligne, suggéré par la console du SDK, mais si quelqu’un peut m’expliquer le pourquoi du comment (pour bien comprendre ce qui a été fait) je suis preneur. D’avance merci

Hello,

Le .toString() a la fin ne donne plus qu’une seule possibilité au type de la variable qui est String donc c’est aussi une bonne solution. C’est juste que si le code ne récupère aucune valeur, ça va planter car un null.toString(), Android n’aime pas trop ça.

Il faudrait soit faire un var fullName: String? au moment de l’initialisation (var textComplet: String? pour @AtomicBob).

Soit faire un if mais au moment où vous récupérez la valeur pour la mettre dans votre variable et forcer la récupération (mais je suis moins fan). Quelque chose du genre :
if memout != null {
textInitial = memout!!.getString("memoire","")
}

Ou alors un elvis operator qui est certainement la solution à privilégier. Ça permet de donner une valeur par défaut à la variable si l’opération que vous demandez renvoie null.
Quelque chose comme : textInitial = memout.getString("memoire","") ?: ""
Ça signifie que si il trouve quelque chose dans memout.getString("memoire",""), textInitial prendra cette valeur. Sinon, textInitial prendra la valeur "".

Après, je ne sais pas à quel point vous êtes avancé dans le développement Android, donc je ne veux pas vous introduire de notions trop complexes qui ne vont que vous embrouiller plus que vous éclairer.

Une string est un texte formé de caractères. Tu en crée une avec ton code :

var fullname = ""

Une String? est un type de variable particulier pouvant contenir une String ou rien !! On appelle cela une variable optionnelle.

On l’utilise pour stocker le résultat d’une opération dont le résultat n’est pas certain à 100%.

Ta fonction preferencesReader.getString() recherche une String dans la base de donnée à partir d’une clé d’identification. Mais que se passe-t-il si l’information cherchée n’existe pas ou a été effacée ? Le programme continue son exécution, faisant des calculs sur une information non existante. Il peut se passer n’importe quoi, d’un calcul erroné à un plantage complet de l’application.

C’est pourquoi la fonction retourne une String conditionnelle, contenant une chaîne ET une information de validité.

Le compilateur n’est pas content parce que tu cherches à stocker une String conditionnelle (symbole String?) dans une String ordinaire. Il n’aime pas les conversions forcées entre deux types de données non compatibles à 100%.

.toString() force la conversion de la String? en une String normale. La syntaxe est correcte, sauf qu’en cas de problème l’application vas planter.

Il faut tester la variable optionnelle avant d’utiliser son contenu. En cas de non-validité elle contient la valeur null

if (fullname != null) {
  // Là, on peut convertir la String? en une String sans risque
  // .... 
}

Ce que Schtipoun te suggère c’était d’écrire quelque chose comme :

var fullname:String? = ""

Cela informe au compilateur que fullname doit être créé comme une variable de type String?.

(code non testé, je n’ai pas bossé en Kotlin depuis longtemps. Mais le principe des variables optionnelles est similaire en Swift pour iOS).

EDIT : Plus d’infos ici :
https://kotlinlang.org/docs/reference/null-safety.html

Il n’y a même pas besoin d’initialiser une variable optionnelle normalement.

Un simple var fullName:String? compile parfaitement :slight_smile:
Il faut juste savoir bien la gérer ensuite pour ne pas provoquer d’exception.

merci à vous deux !!

J’en suis vraiment à débuter et tout n’est pas simple ! :grinning:

Merci à tous les deux.
@schtipoun , j’ai compris du coup l’utilité du Elvis operator mais je croyais que le 2° argument du memout.getString était justement une valeur par défaut au cas où …

Une dernière question sur ce sujet :

Pourquoi dans le tuto Maxime écrit le code comme suit : [ key: « name_key », DefValue:" ") ]

et moi je dois mettre : [ key: « name_key », DefValue:" ") ?: «  »]

Est-ce due à une différence de version de Android Studio ?

Salut @Lexx,

Ce n’est pas un problème d’Android Studio, mais de l’API utilisée.
L’API 29 n’accepte plus cette façon de faire et peut-être certaines API antérieures.

@mbritto a utilisé l’API 23 pour le bloc-notes et elle fonctionne même sans le Elvis.
Même si Maxime a corrigé son code sur Github, en enlevant le Elvis, ça met un warning, mais l’app compile bien.

Donc, il faut ajouter ce petit bout de code à la fin de la ligne (?: " ")

1 « J'aime »

merci @ThonyF

Comme @Lexx Lexx je débute. Merci pour la pertinence et la rapidité des questions.
Vivement que j’en pose une autre !


Salut à toutes et à tous,

Mon problème est le même que celui de Lexx,
mais ne se résout avec aucune des solutions proposées (et testées :sweat_smile:) sur cette discussion…
Quelqu’un peut-il m’aider s’il-vous-plaît ?

Merci :grin:

@Neptranos
À la vue de la capture d’écran, tu n’as pas mis le bout de code ci-dessous à la fin de la dernière ligne de ta fonction onCreate:

?: " "

Ce qui donne ça :

nameUser = sharedPreferences.getString(idUser, " ") ?: " "

Et je me rends compte en tapant la ligne ci-dessus que tu n’as pas tapé correctement cette ligne.

Tu utilises preferencesReader et non sharedPreferences.

@anthonyfassler1
Je vous ai encoyé mon code originel, il est donc normal de ne pas voir ?: " "
Mais comme dit précédemment, j’ai essayé cette solution qui n’a rien résolu de mon côté.

Par ailleurs, je n’ai pas de variable fulltext, même si j’ai bien compris qu’elle correspond à nameUser de mon côté, et je ne vois pas de preferencesEditor dans mon code au lieu de sharedPreferences.

Donc je suis toujours dans l’incompréhension, pourrais-tu être plus clair s’il-te-plaît ?

Néanmoins, merci d’avoir répondu :grin:

Oui désolé, j’ai oublié de changer le fulltext.
Et c’est preferencesReader et non Editor, je crois que je suis fatigué :joy:

Donc,

nameUser = sharedPreferences.getString(idUser, " ") ?: " "

et non :

nameUser = preferencesReader.getString(idUser, " ") ?: " "

nameUser = sharedPreferences.getString(idUser, " ") ?: " "`

AndroidStudio… n’apprécie pas vraiment le sharedPreferences :sweat_smile:
(si je garde un preferencesReader)

En tous cas, le programme ne sauvegarde pas les données ou ne les lit pas…

Je ne comprends pas, encore :kissing:

Peux-tu m’envoyer ton app, car là je ne vois plus rien d’anormal.

Tu veux le fichier .kt ?
Sous quel format ? car .kt ne passe pas pour te l’envoyer