Android Kotlin 基础知识:被调试简介搞糊涂了
Android Basics in Kotlin: confused by Introduction to Debugging
我有一个非常基本的问题。我正在按照建议的顺序阅读开发指南 codelabs,但在“调试介绍”第 6 节:“记录一个 运行 应用程序”时失败了。我发现解释非常混乱,因为对于初学者来说太简单了。
如果某些东西没有按预期工作,我很乐意删除并重新开始,但我还需要确保,随着我的进步,任何缺乏期望的结果都不是因为我的环境。
在本课中,我们需要修改现有代码以使用 Log.d 语句更新应用程序单个 TextView我们看到 ID division_textview 在 phone 屏幕上更新了。
我尝试了很多方法来添加最后的声明
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
但不能将它添加到任何地方,以便在我的模拟器中更新值。我没有收到任何错误,但由于本课中没有“解决方案代码”,而且本课前面的图片都让最终代码的外观变得模糊不清,有人可以帮我解决这个问题吗?
我真的需要确保我的模拟器工作正常(没有报告错误)并且缺少结果是我的代码而不是我的设置。
这是有问题的课程(感谢您的提示!)
来自我的 MainActivity.kt 的代码进一步到下面的有用建议。请注意,我知道这不是 'optimal' 代码,此时我只是在尝试按照说明进行操作。
package com.example.debugging
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
private const val TAG = "MainActivity"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val helloTextView: TextView = findViewById(R.id.division_textview)
helloTextView.text = "Hello, debugging!"
logging()
division()
}
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Thread.sleep(3)
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
fun logging() {
Log.e(TAG, "ERROR: a serious error like an app crash")
Log.w(TAG, "WARN: warns about the potential for serious errors")
Log.i(TAG, "INFO: reporting technical information, such as an operation succeeding")
Log.d(TAG, "DEBUG: reporting technical information useful for debugging")
Log.v(TAG, "VERBOSE: more verbose than DEBUG logs")
}
}
我认为这是一个写得非常草率和错误的教程。 (是的,即使它来自 Google。)如果你在主线程中休眠,在整个 repeat
循环完成之前你不会看到文本视图内容发生变化,所以你只会查看最终值,在 denominator
已经递减为 0 之后。此外,教程声称您将看到它每三秒更改一次,即使带有 Thread.sleep(3)
的代码只会暂停 3 毫秒。然后在他们的实际示例中,他们使用了 Thread.sleep(1)
,这与他们的说明相矛盾。
试试这个代码:
// added to imports:
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.*
// modified division function
fun division() = lifecycleScope.launch {
val numerator = 60
var denominator = 4
repeat(4) {
delay(3000)
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
使用 = lifecycleScope.launch {
将您的函数变成协程,让您可以使用 delay()
函数而不是 Thread.sleep()
,因此主线程有机会实际更新您的文本视图而不是必须等待整个 repeat
循环完成。
这里有另一种不用协程的方法,但不是那么漂亮:
fun division() = with(Handler(Looper.getMainLooper())) {
val numerator = 60
var denominator = 4
repeat(4) { i ->
postDelayed({
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
Log.v(TAG, "${numerator / denominator}")
denominator--
}, i * 3000L)
}
}
我有一个非常基本的问题。我正在按照建议的顺序阅读开发指南 codelabs,但在“调试介绍”第 6 节:“记录一个 运行 应用程序”时失败了。我发现解释非常混乱,因为对于初学者来说太简单了。
如果某些东西没有按预期工作,我很乐意删除并重新开始,但我还需要确保,随着我的进步,任何缺乏期望的结果都不是因为我的环境。
在本课中,我们需要修改现有代码以使用 Log.d 语句更新应用程序单个 TextView我们看到 ID division_textview 在 phone 屏幕上更新了。
我尝试了很多方法来添加最后的声明
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
但不能将它添加到任何地方,以便在我的模拟器中更新值。我没有收到任何错误,但由于本课中没有“解决方案代码”,而且本课前面的图片都让最终代码的外观变得模糊不清,有人可以帮我解决这个问题吗?
我真的需要确保我的模拟器工作正常(没有报告错误)并且缺少结果是我的代码而不是我的设置。
这是有问题的课程(感谢您的提示!)
来自我的 MainActivity.kt 的代码进一步到下面的有用建议。请注意,我知道这不是 'optimal' 代码,此时我只是在尝试按照说明进行操作。
package com.example.debugging
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
private const val TAG = "MainActivity"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val helloTextView: TextView = findViewById(R.id.division_textview)
helloTextView.text = "Hello, debugging!"
logging()
division()
}
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Thread.sleep(3)
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
fun logging() {
Log.e(TAG, "ERROR: a serious error like an app crash")
Log.w(TAG, "WARN: warns about the potential for serious errors")
Log.i(TAG, "INFO: reporting technical information, such as an operation succeeding")
Log.d(TAG, "DEBUG: reporting technical information useful for debugging")
Log.v(TAG, "VERBOSE: more verbose than DEBUG logs")
}
}
我认为这是一个写得非常草率和错误的教程。 (是的,即使它来自 Google。)如果你在主线程中休眠,在整个 repeat
循环完成之前你不会看到文本视图内容发生变化,所以你只会查看最终值,在 denominator
已经递减为 0 之后。此外,教程声称您将看到它每三秒更改一次,即使带有 Thread.sleep(3)
的代码只会暂停 3 毫秒。然后在他们的实际示例中,他们使用了 Thread.sleep(1)
,这与他们的说明相矛盾。
试试这个代码:
// added to imports:
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.*
// modified division function
fun division() = lifecycleScope.launch {
val numerator = 60
var denominator = 4
repeat(4) {
delay(3000)
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
使用 = lifecycleScope.launch {
将您的函数变成协程,让您可以使用 delay()
函数而不是 Thread.sleep()
,因此主线程有机会实际更新您的文本视图而不是必须等待整个 repeat
循环完成。
这里有另一种不用协程的方法,但不是那么漂亮:
fun division() = with(Handler(Looper.getMainLooper())) {
val numerator = 60
var denominator = 4
repeat(4) { i ->
postDelayed({
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
Log.v(TAG, "${numerator / denominator}")
denominator--
}, i * 3000L)
}
}