【问题标题】:Kotlin cant change button propertiesKotlin 无法更改按钮属性
【发布时间】:2021-10-02 16:40:16
【问题描述】:

我在更改 Kotlin 中按钮的属性时遇到问题。那只是在一个功能中,它在所有其他功能中都可以正常工作。这很奇怪,因为我可以在该函数中更改 TextView 的属性。 这是函数:

override fun onResponse(call: Call, response: Response) {
    val body = Klaxon().parse<API_result>(response.body!!.string())

    //setting these textView texts is no problem
    findViewById<TextView>(R.id.windSpeed).text = (body?.wind?.speed?.times(3.6)).toString() + " km/h"
    findViewById<TextView>(R.id.temperature).text = body?.main?.temp.toString() + " C"
    findViewById<TextView>(R.id.airPressure).text = body?.main?.pressure.toString() + " hPa"

    //changing button text is not working and crashes the app
    findViewById<Button>(R.id.fillOutForm).text = "Test"
}

这是整个文件:

class MainActivity : AppCompatActivity() {

    lateinit var fusedLocationProviderClient: FusedLocationProviderClient
    private val client = OkHttpClient()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

        fetchLocation()
    }

    private fun fetchLocation(){
        val task = fusedLocationProviderClient.lastLocation
        if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), 101)
            return
        }
        task.addOnSuccessListener {
            if(it != null){
                apiRequest(it.latitude, it.longitude)
            }
        }
    }

    private fun apiRequest(latitude: Double, longitude: Double){
        var url = "https://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&appid=...&units=metric&lang=en";
        val request = Request.Builder()
            .url(url)
            .build()

        client.newCall(request).enqueue(object : Callback{
            override fun onFailure(call: Call, e: IOException) {
                return
            }

            override fun onResponse(call: Call, response: Response) {
                //code from above
            }
        })
    }
}

data class API_result(
    val main: main?,
    val wind: wind?
)

data class main(
    val temp: Double?,
    val pressure: Int?
)

data class wind(
    val speed: Double?
)

在应用崩溃之前,按钮文本会正确更新。如果我删除“按钮行”,该应用程序运行良好。我真的不知道为什么会这样。

似乎只有 TextViews 在这个功能中工作,因为我还使用密码和电子邮件(也是文本)和开关对其进行了测试。它不适用于这些情况。

我还认识到我可以毫无问题地访问该函数中的 xml 元素(例如按钮),但我无法设置它的属性。 例如,我可以这样做

findViewById<TextView>(R.id.someText).text = findViewById<Button>(R.id.someButton).text

但不是这个

findViewById<Button>(R.id.someButton).text = "exampleText"

堆栈跟踪:

我希望你能帮助我!提前感谢您的帮助!

【问题讨论】:

  • 可以包含堆栈跟踪吗?
  • @gidds 我已将其添加到问题中
  • 您能否显示您的client.newCall() 呼叫周围的代码?它是从哪个线程调用的?另外,请不要发布代码/堆栈跟踪的图片。复制粘贴文本,以便更容易查看和搜索。
  • 进行了更改。如果我将堆栈跟踪粘贴到代码字段中,则它没有被格式化。
  • 当尝试从后台线程更新 UI 时会导致此异常。看到问题仅针对 Button,这很奇怪。您可以尝试打印Thread 名称吗?

标签: android xml api kotlin


【解决方案1】:

我想这里的问题是您正在从非 UI 线程访问 UI 对象,这导致了问题。从非 UI 线程访问 UI 元素会导致未定义的行为

如果您尝试在主线程以外的线程中修改甚至引用 UI 对象,结果可能是异常、静默失败、崩溃和其他未定义的错误行为。

您可以阅读更多关于它的信息here

要解决此问题,您需要从 UI 线程访问 UI 对象,如下所示。在onResponse 中做findViewById&lt;TextView&gt;(R.id.someText) 也不好,因为您确定UI 对象总是在那里。而是在 onCreate 中初始化它们并在任何地方访问引用变量。

lifecycleScope.launch {
        withContext(Dispatchers.Main){
            textView.text = "sometext"
            button.text = "sometext"
            //and so on
        }
    }

如果您的项目中没有协程

runOnUiThread(Runnable { 
        textView.text = "sometext"
            button.text = "sometext"
            //and so on
    })

还有一个类似的问答here

【讨论】:

  • 我应该把它放在我的代码哪里?
  • @philale 在onResponse 内。
  • lifecycleScope、withContext 和 Dispatchers 为红色。我需要定义它们吗?
  • @philale 你需要对应的依赖。随便搜索一下就可以轻松搞定。
  • @philale 实现“org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2”和实现“androidx.lifecycle:lifecycle-livedata-ktx:2.2.0”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
  • 2023-03-13
  • 2011-01-11
  • 2013-03-08
  • 1970-01-01
  • 2016-01-04
相关资源
最近更新 更多