让协程等待 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部分添加日志,找出异常原因。您代码中的其他一切都很好。
我是 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部分添加日志,找出异常原因。您代码中的其他一切都很好。