让协程等待 Kotlin 中的 Jsoup 响应

Make Coroutine wait for Jsoup response in Kotlin

我是 Android 的新手,在理解事物的运作方式时遇到了问题。我制作了一个应用程序来 从页面中抓取 内容,并下载元素,首先使用 AsyncTask 并工作,但由于 AsyncTask 不允许我与 UI Activity 关于进展,我决定改为协程,检查了一个例子,我使用的相同代码似乎不起作用。

我使用了一些日志来尝试确定问题,似乎它没有等待 Jsoup 请求。协程首先调用方法scrapePage()下载HTML和抓取链接,然后调用downloadImages()添加链接到[=35] =] 的下载管理器。在日志中 Log.d("action", "Start Scraping") 被打印出来,但是 Log.d("action", "Page downloaded") 没有,我们仍然从协程中得到 Log.d("action", "End"),这让我认为它不是等待 Jsoup 请求回答,而是去响应为空,导致其余代码无法正常工作。

DownloadService.kt

object DownloadService {

    private val parentJob = Job()
    
    ...

    private val coroutineScope = CoroutineScope(Dispatchers.Main + parentJob +
            coroutineExceptionHandler)

    fun StartService(URL: String, location:String, contx:Context) {

        coroutineScope.launch(Dispatchers.Main) {
            Log.d("action", "Start")
            val links = scrapePage(URL)
            val download = downloadImages(links, location, contx)
            Log.d("action", "End")
        }
    }

    private suspend fun scrapePage(url: String): MainActivity.Scraped =
        withContext(Dispatchers.IO) {
            var URL = url
            var scrape = MainActivity.Scraped()
            try {
                Log.d("action", "Start Scraping")
                var response = Jsoup.connect(URL).get()
                Log.d("action", "Page downloaded")
                response.getElementsByClass("link").forEach {
                    /*Scrape URLs*/
                    Log.d("action", "Add "+link)
                }
            } catch (e: Exception) {
                when(e) {
                    is HttpStatusException -> {
                        System.out.println(e.getStatusCode())
                        scrape.error = true
                        error = true
                    }
                }
            }
            return@withContext scrape
        }

    ...
}

MainActivity.kt

class MainActivity : AppCompatActivity() {
    ...
    fun makeRequest(URL : String) {
        WorkingURL = URL
        var uri = ""
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            uri = MediaStore.Downloads.EXTERNAL_CONTENT_URI.toString()
            log.text = uri
        } else {
            uri = getStoragePath()
            log.text = uri
        }
        DownloadService.StartService(URL, uri, this)
        Log.d("links", DownloadService.getError().toString())
    }
}

我不确定问题出在哪里,也不知道从哪里开始搜索。我知道 Scraping 的代码有效,因为我之前用过 AsyncTask,所以问题似乎是将它传递给协程。

这里 Jsoup.connect(URL).get() 抛出一个错误。所以,Log.d("action", "Page downloaded") 没有被调用。

但是由于您正在处理异常,代码运行 catch 部分并完成挂起函数并继续 downloadImages()


解决方案

首先在scrapePage()函数的catch部分添加日志,找出异常原因。您代码中的其他一切都很好。