【问题标题】:How can I update a var inside a whole kotlin class through a method and then retrieve it updated with another method call如何通过一个方法更新整个 kotlin 类中的 var,然后用另一个方法调用更新它
【发布时间】:2019-02-16 13:19:46
【问题描述】:

我编写了一个 kotlin 类,其中包含一个重写的乐趣和一个将 var 更新到类范围的乐趣(可悲的是,我是 Kotlin 的新手!)

class mySampleClass: sampleReference(){
    var varToBeUpdated:String = "my string" //var in class scope to be updated

    fun updateMyVar(gotString:String){

        //I tried this, it didn't work
        this.varToBeUpdated = gotString
        // also this didn't work
        varToBeUpdated = gotString

    }

    override fun sample(context: Context, intent: Intent){
        //here i need my varToBeUpdated with new string
        runSomeThing(varToBeUpdated)
        //some work to be done here
    }
}

在我调用方法的地方:

myObject.updateMyVar("new string")
myObject.sample()

我想知道如何更新我需要的 var,因为我无法在“有趣的示例”中添加新参数,因为它覆盖了类方法

提前致谢,向大家致以最诚挚的问候:)



更新:添加我的实际代码,因为当我调用覆盖方法时,该类似乎无法保持正确的更新值:

这是我的 BroadcastReceiver,检查何时下载完成并执行一些操作

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

        }
    }
}

这是我的 DownloaderClass 中的部分...

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

【问题讨论】:

  • 如果您将varToBeUpdated 公开,您可以使用myObject.varToBeUpdated=“my string” 访问它
  • 也许我现在的问题是我没有公开它?嗯:无事可做。当我调用该方法时,有些东西再次声明了我的 var,或者只是有些东西阻止我更新它们
  • 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" 你应该删除它。
  • 如果您调用brReceiver.onReceive(...)DownloadBroadcastManager 中的值将被更新。但你不应该那样做。 Android 框架会为您调用它。并且当它发生时,会创建 DownloadBroadcastManager 类的新实例并设置默认值。我们使用 Intent 将数据传递给 BroadcastReceiver,例如创建广播接收器时调用intent.putExtra("filename", "yourFileName"),并在onReceive() 函数中调用intent.getStringExtra("filename")stackoverflow.com/questions/10032480/…
  • 真的非常感谢!

标签: android kotlin broadcastreceiver android-broadcastreceiver


【解决方案1】:

您只需执行以下操作:

  1. 摆脱updateMyVar函数:

    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
        }
    }
    
  2. 直接更新varToBeUpdated属性:

    val myObject = MySampleClass()
    myObject.varToBeUpdated = "new string"
    myObject.sample()
    

更新: 如果您调用brReceiver.onReceive(...)DownloadBroadcastManager 中的值将被更新。但你不应该那样做。 Android 框架 为您调用它。并且当它发生时,会创建 DownloadBroadcastManager 类的新实例并设置默认值。我们使用 Intents 将数据传递给BroadcastReceiver,例如在创建BroadcastReceiver 时调用intent.putExtra("filename", "yourFileName"),并在onReceive() 函数中调用intent.getStringExtra("filename") 以获取值。 Here is how to pass/get data to/from BroadcastReceiver

【讨论】:

  • 我觉得这个方案违反了封装原则。
  • 不,它没有。 Kotlin 有属性kotlinlang.org/docs/reference/properties.html 的概念。要使用属性,我们只需按名称引用它。 varToBeUpdated 是一个属性。 getter 和 setter 是可选的。
  • 我现在只能在电脑上工作.. 似乎有些东西阻止了这个工作。对象可以重新初始化而我没有注意到吗?
  • 您可以在 Android Studio 中通过右键单击属性 -> Find Usage -> 在底部窗口查找 Value write 下拉列表来检查值更新的位置。当您单击它时,您将获得属性更新的所有位置。
  • 好的,我试图找到用法并使用 println() 将一些输出发送到控制台我的结果是在 MainActivity 中确认了更新: println(myObject.varToBeUpdated) //resutl 这里是默认值 myObject.varToBeUpdated = "new string" // 新值注入 println(myObject.varToBeUpdated) // 结果控制台是新的! myObject.sample() // 这里它再次使用默认值...这是怎么回事?在此先感谢,最好的问候 brReceiver.onReceive(context, intent)
【解决方案2】:

根据 kotlin 的文档,您可以像这样为任何变量定义 gettersetter 方法:

var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]

你的情况可能是这样的:

var varToBeUpdated:String = "my string"
    get() = field
    set(value) { field = value }

【讨论】:

    【解决方案3】:

    好的,首先感谢 M.SamiAzar,尤其是 Sergey,感谢他们的回答和令人难以置信的耐心! 不幸的是,当它被框架重新初始化时,BroadcastReceiver 似乎也丢失了我之前放入 Intent 变量的任何额外内容。 我终于解决了这个问题,让我检索我需要的字符串,只需将一行文本写入内部存储中的文件并在我的 BroadcastReceiver 类中检索它。 代码如下:

    这是我在 BroadcastReceiver 类中的“onReceive”方法

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

    这是在我的 DownloadManager 类中添加的代码:

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

    我不知道这是否是“正统”,但它似乎在 atm 工作 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      • 2014-01-13
      • 1970-01-01
      • 2013-01-28
      • 1970-01-01
      相关资源
      最近更新 更多