0

C#/Java Dev 尝试在这里学习 Kotlin。

我正在从我的 Kotlin 应用程序 ping 一个网站,但我无法获取等待的任务结果。'pingResponse'(在等待的函数内)按预期返回 true。但是 'pingResult'(字符串生成器的一部分)总是返回 false。检索结果的正确方法是什么?

package com.android.ews2

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.telephony.TelephonyManager
import android.widget.TextView
import kotlinx.coroutines.*
import java.io.PrintWriter
import java.io.StringWriter
import java.lang.Runnable
import java.net.InetAddress
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

   ObtenerPhoneState(this.applicationContext,this);

    val textMultiLine = findViewById<TextView>(R.id.textMultiLine);

    val mainHandler = Handler(Looper.getMainLooper())

    mainHandler.post(object : Runnable {
        override fun run() {
            refreshUserData(textMultiLine);
            mainHandler.postDelayed(this, 15000)
        }
    })

}

fun refreshUserData(textMultiLine : TextView) {

    var sb = StringBuilder();

    val sdf = SimpleDateFormat("dd/M/yyyy hh:mm:ss")
    val currentDate = sdf.format(Date())

    sb.append(currentDate.toString() + "\n");

    val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager

    sb.append("simOperatorName: " + telephonyManager.simOperatorName+ "\n");

    sb.append("dataActivity: " + telephonyManager.dataActivity + "\n");

    sb.append("callState: " + telephonyManager.callState + "\n");

    sb.append("dataState: " + telephonyManager.dataState + "\n"); 

//This always returns false

    sb.append("pingResult: " + ping() + "\n");

    textMultiLine.text = sb.toString()

}



private fun ping(): Boolean = runBlocking  {

    var pingResponse = false;

    GlobalScope.launch(Dispatchers.IO)

{


    try {
        
        println("Pinging...")

        pingResponse = InetAddress.getByName("www.google.com").isReachable(500);

//This returns true, as expected

        println("Ping result: " + pingResponse);

    } catch (ex: Exception) {

        val sw = StringWriter()
        ex.printStackTrace(PrintWriter(sw))
        val exceptionAsString = sw.toString()
        println(exceptionAsString)

    }

 }
    return@runBlocking pingResponse;
}

}

我尝试过的事情:

  1. 使用 Kotlin 协程
  2. 使用 GlobalScope.Launch
  3. 使用挂起函数
  4. 使用 RunBlocking

在这些实验中,我遇到了一些有趣的错误,例如“类型不匹配:预期的单元,找到布尔值”或“android.os.NetworkOnMainThreadException”。

4

1 回答 1

0

您需要启动一个协程,在不同的上下文中调用该函数,然后使用结果。它看起来类似于:

// launching a coroutine in lifecycleScope, by default it uses Dispatchers.Main context,
// so we can update Views in it
fun refreshUserData(textMultiLine : TextView) = lifecycleScope.launch {
    var sb = StringBuilder()
    // ...
    sb.append("pingResult: " + ping() + "\n");

    textMultiLine.text = sb.toString()
}

// using withContext() we are switching the context of function execution
// it will execute in background thread
private suspend fun ping(): Boolean = withContext(Dispatchers.IO)  {

    var pingResponse = false

    try {
        println("Pinging...")
        pingResponse = InetAddress.getByName("www.google.com").isReachable(500)
        println("Ping result: $pingResponse")

    } catch (ex: Exception) {
        val sw = StringWriter()
        ex.printStackTrace(PrintWriter(sw))
        val exceptionAsString = sw.toString()
        println(exceptionAsString)
    }

    return@withContext pingResponse
}

要使用lifecycleScope添加依赖项:

implementation 'androidx.lifecycle:lifecycle-runtime-ktx:$2.4.0'
于 2022-01-14T20:32:36.310 回答