Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/202.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 无法更改Kotlin中的全局变量值_Android_Kotlin - Fatal编程技术网

Android 无法更改Kotlin中的全局变量值

Android 无法更改Kotlin中的全局变量值,android,kotlin,Android,Kotlin,我正在更改方法中的全局变量值,并尝试稍后返回它 在FetchData.kt中(被调用的类) var homeFeed: HomeFeed? = null // the variable that needs to be changed fun execute() { val client = OkHttpClient() val url = "..." val request = Request.Builder().url(url).bui

我正在更改方法中的全局变量值,并尝试稍后返回它

在FetchData.kt中(被调用的类)

var homeFeed: HomeFeed? = null     // the variable that needs to be changed 

fun execute() {


    val client = OkHttpClient()
    val url =
        "..."
    val request = Request.Builder().url(url).build()

    val res = client.newCall(request).enqueue(object : Callback {

        override fun onFailure(call: Call, e: IOException) {

            e.printStackTrace()

        }

        override fun onResponse(call: Call, response: Response) {

            val ch = response?.body?.string()

            val gson = GsonBuilder().create()
            homeFeed= gson.fromJson(ch, HomeFeed::class.java)  // where the change happens

        }

    })

}

   fun GetData(): HomeFeed? {

       return homeFeed
   } 
在MainActivity.kt中

override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

   btn.setOnClickListener {

      val  destination = "destination"

      val places = FetchData(destination)

      places.execute()
      val data = places.GetData()
   }
}
问题在于MainActivity中的Null值被分配给“data”变量,就好像返回的“homeFeed”变量根本没有更改一样

调试了代码,以确保api调用不会出现错误,并且变量在方法内部更改(但不在方法外部!)


我真的受不了了,有什么帮助吗?

您在发出异步请求后立即调用了
getData()
,因此它没有机会被更新。异步函数不会立即返回。一些后台线程执行某些操作(网络请求),在本例中,当结果在将来某个时间返回时,调用
onResponse

就像你按钮上的听众。监听器中的代码不会立即运行,而是在将来某个时候用户按下它时运行

您的函数可以接受一个回调参数,而不是使用此成员属性,该参数在结果就绪时调用:

fun execute(resultHandler: (HomeFeed) -> Unit) {
    //... snip ...

    client.newCall(request).enqueue(object : Callback {
        // ... snip ...
        override fun onResponse(call: Call, response: Response) {
            val ch = response?.body?.string()
            val gson = GsonBuilder().create()
            resultHandler(gson.fromJson(ch, HomeFeed::class.java))
        }
    })

}
   btn.setOnClickListener {
      val destination = "destination"
      val places = FetchData(destination)
      places.execute { homeFeedData ->
          // Do something with homeFeedData when it arrives
      }
   }
然后,当调用它时,传递一个lambda,当结果准备就绪时将调用该lambda:

fun execute(resultHandler: (HomeFeed) -> Unit) {
    //... snip ...

    client.newCall(request).enqueue(object : Callback {
        // ... snip ...
        override fun onResponse(call: Call, response: Response) {
            val ch = response?.body?.string()
            val gson = GsonBuilder().create()
            resultHandler(gson.fromJson(ch, HomeFeed::class.java))
        }
    })

}
   btn.setOnClickListener {
      val destination = "destination"
      val places = FetchData(destination)
      places.execute { homeFeedData ->
          // Do something with homeFeedData when it arrives
      }
   }

为什么要使用全局变量呢?这是一种非常糟糕的做法。@marstran我知道,但在这种情况下,当我在本地(在Onresponse方法中)声明它时,我无法返回它,因为该方法被重写并且不能返回任何内容,但是有更好的方法来捕获网络调用的结果…client.newCall(request).enqueue(…)是异步的。您不能调用places.execute()并立即在places.GetData()中调用结果。您应该使用反应式或回调方法。您可以使用val response=client.newCall(request).execute(),但它需要在非主线程中调用。这是正确的解决方案,现在修改什么使execute函数返回这个HomeFeedIt不能返回它,因为函数立即返回,并且它正在后台线程中执行一些需要一段时间的操作。(可以将其写入阻塞调用,但这将冻结UI并导致ANR崩溃。)您可以使用我标记为“Dosomething with HomeFeed”的回调将该值分配给变量。这是您将继续处理响应的逻辑流程的地方。问题是,我希望在外部(places.execute{})进行所有处理,所有处理都基于此homeFeedData,当我将值分配给“.execute”中的var变量并希望在外部恢复它时,我发现变量unchangedSounds与您最初犯的错误相同。如果立即检查变量,则该变量尚未更新。为了完成您所描述的,您必须使用协同程序,它允许函数挂起,然后在某些后台任务完成后继续它们停止的地方。看起来好像有人写了一篇文章来使用协同程序。通常情况下,协同程序并非易学易懂,但可以产生更干净的代码。关于在Android上使用协同程序进行联网(我没有读过,所以不能担保)。