Kotlin 使用协程时出现NetworkOnMainThreadException
我一直在尝试在按下按钮时验证网络连接状态。 据此,本守则Kotlin 使用协程时出现NetworkOnMainThreadException,kotlin,kotlin-coroutines,networkonmainthread,Kotlin,Kotlin Coroutines,Networkonmainthread,我一直在尝试在按下按钮时验证网络连接状态。 据此,本守则 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) findViewById<Button>(R.id.button).setOnClickListener { findViewById
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
findViewById<TextView>(R.id.logText).setText("Button Pressed"+counter++)
GlobalScope.launch (Dispatchers.Main) {
val result = withContext(Dispatchers.Default){
isInternetAvailable()
}
println(result.toString())
}
}
}
suspend fun isInternetAvailable():Boolean {
return withContext(Dispatchers.Main) {
try {
val ipAddr = InetAddress.getByName("google.com")
//You can replace it with your name
println("1$ipAddr")
return@withContext !ipAddr.equals("")
} catch (e: Exception) {
println("within exception$e")
return@withContext false;
}
}
}
有人能解释一下NetworkOnMainThread异常的原因吗
非常感谢。withContext(Dispatchers.Main)
意味着在主线程的lambda中运行代码,这是不允许阻塞代码的。对于网络请求,应使用Dispatchers.IO
另外,不要使用GlobalScope,因为它会泄露您的活动。使用lifecycleScope
lifecycleScope
默认情况下使用主线程,因此在使用它时,除非进行阻塞调用,否则不必指定调度程序
在执行阻塞调用时,通常会使挂起函数切换到相应的调度程序,这样您就可以从任何调度程序安全地调用它们。这意味着您的挂起函数不会阻止调用,并且可以从协同程序调用,而无需将它们包装在withContext
中
因此,通过以上所有操作,您的代码将变成:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
findViewById<TextView>(R.id.logText).setText("Button Pressed"+counter++)
lifecycleScope.launch {
val result = isInternetAvailable()
println(result.toString())
}
}
}
suspend fun isInternetAvailable(): Boolean {
return withContext(Dispatchers.IO){
try {
val ipAddr = InetAddress.getByName("google.com")
//You can replace it with your name
println("1$ipAddr")
return@withContext !ipAddr.equals("")
} catch (e: Exception) {
println("within exception$e")
return@withContext false;
}
}
}
override-fun-onCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById(R.id.button).setOnClickListener{
findviewbyd(R.id.logText).setText(“按下按钮”+计数器++)
生命周期望远镜发射{
val结果=isInternetAvailable()
println(result.toString())
}
}
}
suspend fun isInternetAvailable():布尔值{
返回withContext(Dispatchers.IO){
试一试{
val ipAddr=InetAddress.getByName(“google.com”)
//你可以用你的名字代替它
println(“1$ipAddr”)
return@withContext!ipAddr.equals(“”)
}捕获(e:例外){
println(“例外$e内”)
return@withContext虚假的;
}
}
}
withContext(Dispatchers.Main)
意味着在主线程的lambda中运行代码,这是不允许阻塞代码的。对于网络请求,应使用Dispatchers.IO
另外,不要使用GlobalScope,因为它会泄露您的活动。使用lifecycleScope
lifecycleScope
默认情况下使用主线程,因此在使用它时,除非进行阻塞调用,否则不必指定调度程序
在执行阻塞调用时,通常会使挂起函数切换到相应的调度程序,这样您就可以从任何调度程序安全地调用它们。这意味着您的挂起函数不会阻止调用,并且可以从协同程序调用,而无需将它们包装在withContext
中
因此,通过以上所有操作,您的代码将变成:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
findViewById<TextView>(R.id.logText).setText("Button Pressed"+counter++)
lifecycleScope.launch {
val result = isInternetAvailable()
println(result.toString())
}
}
}
suspend fun isInternetAvailable(): Boolean {
return withContext(Dispatchers.IO){
try {
val ipAddr = InetAddress.getByName("google.com")
//You can replace it with your name
println("1$ipAddr")
return@withContext !ipAddr.equals("")
} catch (e: Exception) {
println("within exception$e")
return@withContext false;
}
}
}
override-fun-onCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById(R.id.button).setOnClickListener{
findviewbyd(R.id.logText).setText(“按下按钮”+计数器++)
生命周期望远镜发射{
val结果=isInternetAvailable()
println(result.toString())
}
}
}
suspend fun isInternetAvailable():布尔值{
返回withContext(Dispatchers.IO){
试一试{
val ipAddr=InetAddress.getByName(“google.com”)
//你可以用你的名字代替它
println(“1$ipAddr”)
return@withContext!ipAddr.equals(“”)
}捕获(e:例外){
println(“例外$e内”)
return@withContext虚假的;
}
}
}