Android kotlin 挂起函数“getInfo”只能从协程或另一个挂起函数中调用

问题描述 投票:0回答:1

我收到以下错误:

suspend function 'getInfo' should be called only from a coroutine or another suspend function

你能告诉我我做错了什么吗?

import android.appwidget.AppWidgetManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.util.Log
import com.myapp.test.WakeLocker.acquire
import com.myapp.test.WakeLocker.release
import org.json.JSONObject
import java.util.concurrent.ExecutionException

class WidgetService : BroadcastReceiver() {
    var json = JSONObject()
    override fun onReceive(context: Context, intent: Intent) {
        //wake the device
        acquire(context)

        //increase the number in the widget
        val preferences = context.getSharedPreferences("PREFS", 0)
        val urlCode = preferences.getString("urlCode", "")
        Log.d("WidgetService1", urlCode!!)
        if (urlCode != "") {
            val getPack = GetPack(urlCode)
            json = try {
                getPack.getInfo()
            } catch (e: ExecutionException) {
                throw RuntimeException(e)
            } catch (e: InterruptedException) {
                throw RuntimeException(e)
            }
            val editor = preferences.edit()
            editor.putString("json", json.toString())
            editor.apply()
        }

        //force widget update
        val widgetIntent = Intent(context, MyWidget::class.java)
        widgetIntent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
        val ids = AppWidgetManager.getInstance(context)
            .getAppWidgetIds(ComponentName(context, MyWidget::class.java))
        widgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
        context.sendBroadcast(widgetIntent)
        Log.d("WidgetService", "Widget set to update!")

        //go back to sleep
        release()
    }
}

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.json.JSONArray
import org.json.JSONObject
import org.jsoup.Jsoup
import java.io.IOException

class GetPack(id: String) {
    private val baseURL = "http://192.xxx.xxx.xxx"
    private val finalURL = "$baseURL:8080"

    suspend fun getInfo(): JSONObject = withContext(Dispatchers.IO) {
        val json = JSONObject()
        try {
            val document = Jsoup.connect(finalURL).get()
            val steps = JSONArray()
            val elements = document.select("#progressTracker-container > div")
            for (ele in elements) {
                val item = JSONObject()
                val reached = ele.attr("data-reached") == "reached"
                val message = ele.select(".milestone-primaryMessage").first().ownText()
                val data = ele.select(".milestone-primaryMessage > .nowrap").text()
                item.put("reached", reached)
                item.put("message", message)
                item.put("data", data)
                steps.put(item)
            }
            val primaryStatus = document.getElementById("primaryStatus")
            json.put("status", primaryStatus.text())
            json.put("steps", steps)
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
        json
    }
}
dependencies {

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    implementation 'org.jsoup:jsoup:1.11.2'
}
android kotlin kotlin-coroutines coroutine
1个回答
0
投票

suspend fun getInfo()
班级的
GetPack
被提及为
suspend
。在 Kotlin 中,挂起函数应该从挂起函数或协程中调用。

关于协程的更多信息:https://developer.android.com/kotlin/coroutines/coroutines-adv

答案:

您可以执行以下任一操作来解决此错误:

  1. suspend
    中删除
    getInfo()
    并使其变得简单
    fun getInfo()
    。但我的建议是不要这样做,因为我们在这里进行 Json 解析,这可能需要时间。
  2. 相反,在
    WidgetService
    类中,您可以使用 IO 调度程序启动协程,如下所示:
1. Add implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0' in app build gradle. 
2. Use lifecycleScope.launch(Dispatchers.IO) {} as follow

        lifecycleScope.launch(Dispatchers.IO) {
            val getPack = GetPack(urlCode)
            json = try {
                getPack.getInfo()
            } catch (e: ExecutionException) {
                throw RuntimeException(e)
            } catch (e: InterruptedException) {
                throw RuntimeException(e)
            }
            val editor = preferences.edit()
            editor.putString("json", json.toString())
            editor.apply()
        }

© www.soinside.com 2019 - 2024. All rights reserved.