J'ai écrit une classe kotlin avec un plaisir écrasé et un plaisir de mettre à jour une variable dans la portée de la classe (je suis tragiquement nouveau à Kotlin!)
var brReceiver = DownloadBroadcastManager() // shows when download is completed println("myTag - ${brReceiver.myClassFilename}, ${brReceiver.myClassExtension}: originals") //here shows the default: it's right val intent = Intent(context, MainActivity::class.java) brReceiver.myClassFilename = myTitle // inject filename brReceiver.myClassExtension = ".mp3" // inject file extension println("myTag - ${brReceiver.myClassFilename}, ${brReceiver.myClassExtension}: modified") // here it shows my class property as correctly updated brReceiver.onReceive(context, intent) // here, as calling the override fun, it get back to default value of the property
À l'endroit où J'appelle les méthodes que je fais:
class DownloadBroadcastManager: BroadcastReceiver() { var myClassFilename:String = "default" var myClassExtension:String = ".default" override fun onReceive(context: Context, intent: Intent) { val action = intent.action if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) { //Show a notification // here there's a log to check if var are updated println("myTag - variables $myClassFilename, $myClassExtension") Toast.makeText(context, "Download of $myClassFilename$myClassExtension completed", Toast.LENGTH_LONG).show() // richiama azioni come player o display image o altro? //player var uri = Uri.parse (Environment.getExternalStorageDirectory().getPath() + "/Download/$myClassFilename$myClassExtension") //myClassExtension is ".mp3", dot is included, however it seems class is re-intialized as i call the method println("myTag - uri: $uri") println("myTag - context: $context") var mPlayer = MediaPlayer() // I added this declaration (that's be re-done later) cause I had a problem in making the player running (of course giving it a valid path to a valid file). Now this is "junk code" mPlayer.stop() mPlayer.reset() mPlayer.release() mPlayer = MediaPlayer.create(context, uri) // here there's the proper declaration + initialization mPlayer.start() } } }
Je me demande comment je peux mettre à jour la var dont j'ai besoin, car je ne peux pas ajouter de nouveaux arguments dans le "fun sample", à cause du fait il remplace une méthode de classe
Merci d'avance, meilleures salutations à tous :)
MISE À JOUR: ajoutez mon code actuel, car la classe semble incapable de conserver la bonne valeur mise à jour lorsque j'appelle la méthode de remplacement:
Voici mon BroadcastReceiver, pour vérifier si le téléchargement est terminé et effectuer une action
myObject.updateMyVar("new string") myObject.sample()
3 Réponses :
En fonction des documents de kotlin, vous pouvez définir les méthodes getter
et setter
pour n'importe quelle variable comme ceci:
var varToBeUpdated:String = "my string" get() = field set(value) { field = value }
dans votre cas c'est peut être quelque chose comme:
var <propertyName>[: <PropertyType>] [= <property_initializer>] [<getter>] [<setter>]
Vous pouvez simplement faire ce qui suit:
Débarrassez-vous de la fonction updateMyVar
:
val myObject = MySampleClass() myObject.varToBeUpdated = "new string" myObject.sample()
Mettre à jour directement la propriété varToBeUpdated
:
class MySampleClass: SampleReference(){ var varToBeUpdated:String = "my string" //var in class scope to be updated override fun sample(context: Context, intent: Intent){ //here i need my varToBeUpdated with new string runSomeThing(varToBeUpdated) //some work to be done here } }
Mise à jour:
Si vous appelez brReceiver.onReceive (...)
, les valeurs dans DownloadBroadcastManager
sont mises à jour. Mais tu ne devrais pas faire ça. Le framework Android l'appelle pour vous. Et quand cela se produit, une nouvelle instance de la classe DownloadBroadcastManager
est créée et les valeurs par défaut sont définies. Nous utilisons Intents pour transmettre des données à BroadcastReceiver
, par exemple appelez intent.putExtra ("filename", "yourFileName")
lorsque vous créez BroadcastReceiver
et appelez intent.getStringExtra ("filename")
dans Fonction onReceive ()
pour obtenir la valeur. Voici comment passer / obtenir des données vers / depuis BroadcastReceiver
Je pense que cette solution viole le principe d'encapsulation.
Non, ce n'est pas le cas. Kotlin a un concept de propriétés kotlinlang.org/docs/reference/properties.html . Pour utiliser une propriété, nous y faisons simplement référence par son nom. varToBeUpdated
est une propriété. Le getter et le setter sont facultatifs.
Je ne pourrais travailler sur PC que maintenant .. il semble que quelque chose empêche cela de fonctionner. L'objet peut-il être réinitialisé et je ne peux pas le remarquer?
Vous pouvez vérifier dans Android Studio où la valeur est mise à jour en cliquant avec le bouton droit de la souris sur la propriété -> Rechercher l'utilisation -> dans la fenêtre du bas, recherchez la liste déroulante Value write
. Lorsque vous cliquez dessus, vous obtenez tous les endroits où la propriété est mise à jour.
Ok, j'ai essayé de trouver une utilisation et aussi d'envoyer une sortie à la console avec println () Mon résultat est que dans MainActivity la mise à jour est confirmée: println (myObject.varToBeUpdated) // resutl voici celui par défaut myObject.varToBeUpdated = "new string "// nouvelle injection de valeur println (myObject.varToBeUpdated) // résultat dans la console voici la nouvelle! myObject.sample () // ici il fonctionne à nouveau avec la valeur par défaut ... Que se passe-t-il ici? Merci d'avance, meilleures salutations brReceiver.onReceive (contexte, intention)
Dans find usage -> Value write, il ne montre plus de mises à jour après ma dernière (qui est la bonne). Je ne sais vraiment pas pourquoi il reste sur la valeur par défaut lorsque j'appelle la méthode de classe
J'ai fait un autre test: j'ai créé une nouvelle méthode, retournant simplement la var qui devrait être mise à jour ... et ça marche? Cela peut-il être un problème lié au processus prioritaire ???
Quand je mets le journal au début de la méthode sample ()
, je vois la valeur mise à jour '"new string"'. Peut-être que vous utilisez la référence à MySampleClass
qui n'est pas mis à jour. C'est difficile à dire sans voir votre code. Si vous mettez à jour votre question avec le code complet, les journaux, les commentaires Nous trouverons la raison.
D'accord, d'abord merci à M.SamiAzar et surtout à Sergey, pour leurs réponses et pour l'incroyable patience! Malheureusement, il semble que, comme il est réinitialisé par le framework, le BroadcastReceiver perd également tous les extras que j'ai précédemment mis dans la variable Intent. J'ai finalement résolu ce problème, me permettant de récupérer les chaînes dont j'avais besoin, en écrivant seulement une ligne de texte dans un fichier de la mémoire interne et en la récupérant dans ma classe BroadcastReceiver. Voici le code:
ceci est mon méthond "onReceive" dans la classe BroadcastReceiver
// strore into an internal storage file the data of title and extensione for the file's gonna be downloaded val myStoredFile:String = "storeDownloadedData" val data:String = "$myTitle,.mp3" val fileOutputStream: FileOutputStream // write file in internal storage try { fileOutputStream = context.openFileOutput(myStoredFile, Context.MODE_PRIVATE) fileOutputStream.write(data.toByteArray()) }catch (e: Exception){ e.printStackTrace() } // it notifies when download is completed val intent = Intent(context, MainActivity::class.java) var brReceiver = DownloadBroadcastManager()
voici le code ajouté dans ma classe DownloadManager:
override fun onReceive(context: Context, intent: Intent) { val action = intent.action Log.i("Receiver", "myTag - Broadcast received: " + action) var myFilename = "deafult" if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) { // read the previously created file from internal storage var fileInputStream: FileInputStream? = null fileInputStream = context.openFileInput("storeDownloadedData") var inputStreamReader: InputStreamReader = InputStreamReader(fileInputStream) val bufferedReader: BufferedReader = BufferedReader(inputStreamReader) // here setting string var and stringbuilder var to catch the text updated outside the while loop val stringBuilder: StringBuilder = StringBuilder() var text: String? = null var sumText:java.lang.StringBuilder? = null // while loop for reading the file line by line (in this case the file can contains just one line a time) while ({ text = bufferedReader.readLine(); text }() != null) { sumText = stringBuilder.append(text) } // convert stringBuilder to a list of string splitting the original string obtained by file reading var secondText:String = "default" println("myTag - text: $text, $sumText") if (sumText != null){ secondText = sumText.toString() var listFromText = secondText.split(",") // set filename to the title contained in the string myFilename = listFromText[0] } //player - finally play the file retrieving the title from the file in internal storage var uri = Uri.parse (Environment.getExternalStorageDirectory().getPath() + "/Download/$myFilename.mp3") println("myTag - uri: $uri") println("myTag - context: $context") var mPlayer = MediaPlayer.create(context, uri) mPlayer.start() }
Je ne sais pas si c'est "ortodox", mais cela semble fonctionner atm :)
Si vous rendez
varToBeUpdated
public, vous pouvez y accéder en utilisantmyObject.varToBeUpdated = “my string”
peut-être que mon problème maintenant est que je ne l'ai pas déclaré public? Hmm: rien à faire. Quelque chose déclare à nouveau mon var lorsque j'appelle la méthode ou simplement quelque chose m'empêche de les mettre à jour
var mPlayer = MediaPlayer () // J'ai ajouté cette déclaration (qui sera refaite plus tard) car j'ai eu un problème pour faire fonctionner le lecteur (bien sûr en lui donnant un chemin valide vers un fichier valide). Maintenant, c'est du "code indésirable"
, vous devriez probablement le supprimer.Si vous appelez
brReceiver.onReceive (...)
, les valeurs dansDownloadBroadcastManager
sont mises à jour. Mais tu ne devrais pas faire ça. Le framework Android l'appelle pour vous. Et quand cela se produit, une nouvelle instance de la classeDownloadBroadcastManager
est créée et les valeurs par défaut sont définies. Nous utilisons des intentions pour transmettre des données à BroadcastReceiver, par exemple appelezintent.putExtra ("filename", "yourFileName")
lorsque vous créez BroadcastReceiver, et appelezintent.getStringExtra ("filename")
dans votreonReceive ()
fonction. stackoverflow.com/questions/10032480/… < / a>Vraiment merci beaucoup!
Ok, j'ai eu l'occasion de le vérifier à nouveau. J'ai supprimé l'appel que j'ai fait à la méthode, car elle est en effet exécutée par le framework lui-même comme vous l'avez dit ... Mais il recrée toujours l'objet et ... Il perd l'intention avec les extras! Quand il s'exécute en premier, il obtient l'intention, dans le deuxième appel automatique, il réinitialise l'objet et je ne sais pas comment conserver ou renvoyer l'intention avec des extras ... C'est un Odissey, je suis désolé je suis un parfait noob