简体   繁体   English

在 Kotlin 中让 Coroutine 等待 Jsoup 响应

[英]Make Coroutine wait for Jsoup response in Kotlin

I'm kind of new developing with Android, and have problems understanding how things works.我是使用 Android 开发的新手,并且在理解事物的工作原理方面存在问题。 I made an app to scrape content from a page, and download elements, first with AsyncTask and worked, but since AsyncTask doesn't let me communicate with the UI Activity on progress, i decided to change to coroutines, checked an example, and the same code i used doesn't seems to work.我制作了一个应用程序来从页面中抓取内容并下载元素,首先使用 AsyncTask 并工作,但由于 AsyncTask 不允许我在进行中与 UI Activity 进行通信,因此我决定更改为协程,检查了一个示例,然后我使用的相同代码似乎不起作用。

I used a few logs to try to determine the problem, and seems like it doesn't wait for the Jsoup request.我使用了一些日志来尝试确定问题,并且似乎没有等待Jsoup请求。 The coroutine first calls a method scrapePage() to download the HTML and scrape the links, and then calls downloadImages() to add the links to Android's DownloadManager.协程首先调用方法scrapePage()下载 HTML 并抓取链接,然后调用downloadImages()将链接添加到 Android 的 DownloadManager。 In the logs Log.d("action", "Start Scraping") is printed, but Log.d("action", "Page downloaded") doesn't, still we get Log.d("action", "End") from the coroutine, which makes me think that instead of waiting for the Jsoup request to answer, it goes with an empty response, causing the rest of the code to not work correctly.在日志中Log.d("action", "Start Scraping")被打印,但Log.d("action", "Page downloaded")没有,我们仍然得到Log.d("action", "End")来自协程,这让我觉得不是等待 Jsoup 请求响应,而是带有空响应,导致其余代码无法正常工作。

DownloadService.kt下载服务.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主活动.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())
    }
}

I am not sure where the problem is, nor where to start searching.我不确定问题出在哪里,也不知道从哪里开始搜索。 I know the code for the Scraping works, because i used it before with AsyncTask, so the problem seems to be passing it to coroutines.我知道Scraping的代码有效,因为我之前在 AsyncTask 中使用过它,所以问题似乎是将它传递给协程。

Here Jsoup.connect(URL).get() is throwing an error.这里Jsoup.connect(URL).get()抛出错误。 so, Log.d("action", "Page downloaded") is not called.因此,不会调用Log.d("action", "Page downloaded")

But since you are handling the exception, the code runs the catch part and completes the suspend function and moves on to downloadImages() .但是由于您正在处理异常,因此代码运行 catch 部分并完成挂起功能并转到downloadImages()


Solution解决方案

First, add a log in the catch part of scrapePage() function and find out what is causing the exception.首先,在scrapePage()函数的catch 部分添加日志并找出导致异常的原因。 Everything else in your code is good.代码中的其他所有内容都很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM