2
votes

Comment puis-je mettre à jour un var dans toute une classe kotlin via une méthode, puis le récupérer mis à jour avec un autre appel de méthode

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()


6 commentaires

Si vous rendez varToBeUpdated public, vous pouvez y accéder en utilisant myObject.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 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 des intentions pour transmettre des données à BroadcastReceiver, par exemple appelez intent.putExtra ("filename", "yourFileName") lorsque vous créez BroadcastReceiver, et appelez intent.getStringExtra ("filename") dans votre onReceive () 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


3 Réponses :


1
votes

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>]


0 commentaires

1
votes

8 commentaires

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.



0
votes

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 :)


0 commentaires