pull/49/head
kunfei 5 years ago
parent 9bf14ed479
commit 845999f9f6
  1. 3
      app/src/main/java/io/legado/app/model/Rss.kt
  2. 5
      app/src/main/java/io/legado/app/model/rss/Result.kt
  3. 4
      app/src/main/java/io/legado/app/model/rss/RssParser.kt
  4. 14
      app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt
  5. 6
      app/src/main/java/io/legado/app/ui/rss/article/RssArticlesActivity.kt
  6. 41
      app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt

@ -5,6 +5,7 @@ import io.legado.app.data.entities.RssSource
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeRule
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.model.rss.Result
import io.legado.app.model.rss.RssParserByRule import io.legado.app.model.rss.RssParserByRule
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -18,7 +19,7 @@ object Rss {
pageUrl: String? = null, pageUrl: String? = null,
scope: CoroutineScope = Coroutine.DEFAULT, scope: CoroutineScope = Coroutine.DEFAULT,
context: CoroutineContext = Dispatchers.IO context: CoroutineContext = Dispatchers.IO
): Coroutine<MutableList<RssArticle>> { ): Coroutine<Result> {
return Coroutine.async(scope, context) { return Coroutine.async(scope, context) {
val analyzeUrl = AnalyzeUrl(pageUrl ?: rssSource.sourceUrl) val analyzeUrl = AnalyzeUrl(pageUrl ?: rssSource.sourceUrl)
val body = analyzeUrl.getResponseAwait(rssSource.sourceUrl).body val body = analyzeUrl.getResponseAwait(rssSource.sourceUrl).body

@ -0,0 +1,5 @@
package io.legado.app.model.rss
import io.legado.app.data.entities.RssArticle
data class Result(val articles: MutableList<RssArticle>, val nextPageUrl: String?)

@ -12,7 +12,7 @@ import java.io.StringReader
object RssParser { object RssParser {
@Throws(XmlPullParserException::class, IOException::class) @Throws(XmlPullParserException::class, IOException::class)
fun parseXML(xml: String, sourceUrl: String): MutableList<RssArticle> { fun parseXML(xml: String, sourceUrl: String): Result {
val articleList = mutableListOf<RssArticle>() val articleList = mutableListOf<RssArticle>()
var currentArticle = RssArticle() var currentArticle = RssArticle()
@ -105,7 +105,7 @@ object RssParser {
Debug.log(sourceUrl, "┌获取文章链接") Debug.log(sourceUrl, "┌获取文章链接")
Debug.log(sourceUrl, "${it.link}") Debug.log(sourceUrl, "${it.link}")
} }
return articleList return Result(articleList, null)
} }
/** /**

@ -6,12 +6,14 @@ import io.legado.app.data.entities.RssArticle
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.model.Debug import io.legado.app.model.Debug
import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeRule
import io.legado.app.utils.NetworkUtils
object RssParserByRule { object RssParserByRule {
@Throws(Exception::class) @Throws(Exception::class)
fun parseXML(body: String?, rssSource: RssSource): MutableList<RssArticle> { fun parseXML(body: String?, rssSource: RssSource): Result {
val sourceUrl = rssSource.sourceUrl val sourceUrl = rssSource.sourceUrl
var nextUrl: String? = null
if (body.isNullOrBlank()) { if (body.isNullOrBlank()) {
throw Exception( throw Exception(
App.INSTANCE.getString( App.INSTANCE.getString(
@ -37,6 +39,14 @@ object RssParserByRule {
Debug.log(sourceUrl, "┌获取列表") Debug.log(sourceUrl, "┌获取列表")
val collections = analyzeRule.getElements(ruleArticles) val collections = analyzeRule.getElements(ruleArticles)
Debug.log(sourceUrl, "└列表大小:${collections.size}") Debug.log(sourceUrl, "└列表大小:${collections.size}")
if (!rssSource.ruleNextPage.isNullOrEmpty()) {
Debug.log(sourceUrl, "┌获取下一页Url")
nextUrl = analyzeRule.getString(rssSource.ruleNextPage)
if (nextUrl.isNotEmpty()) {
nextUrl = NetworkUtils.getAbsoluteURL(sourceUrl, nextUrl)
}
Debug.log(sourceUrl, "└获取下一页Url:$nextUrl")
}
val ruleTitle = analyzeRule.splitSourceRule(rssSource.ruleTitle) val ruleTitle = analyzeRule.splitSourceRule(rssSource.ruleTitle)
val rulePubDate = analyzeRule.splitSourceRule(rssSource.rulePubDate) val rulePubDate = analyzeRule.splitSourceRule(rssSource.rulePubDate)
val ruleDescription = analyzeRule.splitSourceRule(rssSource.ruleDescription) val ruleDescription = analyzeRule.splitSourceRule(rssSource.ruleDescription)
@ -54,7 +64,7 @@ object RssParserByRule {
if (reverse) { if (reverse) {
articleList.reverse() articleList.reverse()
} }
return articleList return Result(articleList, nextUrl)
} }
} }

@ -110,13 +110,13 @@ class RssArticlesActivity : VMBaseActivity<RssArticlesViewModel>(R.layout.activi
if (viewModel.isLoading) return if (viewModel.isLoading) return
if (loadMoreView.hasMore && adapter.getActualItemCount() > 0) { if (loadMoreView.hasMore && adapter.getActualItemCount() > 0) {
loadMoreView.rotate_loading.show() loadMoreView.rotate_loading.show()
viewModel.loadContent() viewModel.loadMore()
} }
} }
override fun loadFinally() { override fun loadFinally(hasMore: Boolean) {
refresh_recycler_view.stopLoading() refresh_recycler_view.stopLoading()
if (viewModel.hasMore) { if (hasMore) {
loadMoreView.startLoad() loadMoreView.startLoad()
} else { } else {
loadMoreView.noMore() loadMoreView.noMore()

@ -9,6 +9,8 @@ import io.legado.app.data.entities.RssArticle
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.model.Rss import io.legado.app.model.Rss
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.withContext
class RssArticlesViewModel(application: Application) : BaseViewModel(application) { class RssArticlesViewModel(application: Application) : BaseViewModel(application) {
@ -18,6 +20,7 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application
val titleLiveData = MutableLiveData<String>() val titleLiveData = MutableLiveData<String>()
var isLoading = true var isLoading = true
var order = System.currentTimeMillis() var order = System.currentTimeMillis()
var nextPageUrl: String? = null
fun initData(intent: Intent, finally: () -> Unit) { fun initData(intent: Intent, finally: () -> Unit) {
execute { execute {
@ -40,15 +43,24 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application
rssSource?.let { rssSource -> rssSource?.let { rssSource ->
Rss.getArticles(rssSource, null) Rss.getArticles(rssSource, null)
.onSuccess(IO) { .onSuccess(IO) {
it?.let { nextPageUrl = it?.nextPageUrl
it.forEach { rssArticle -> it?.articles?.let { list ->
list.forEach { rssArticle ->
rssArticle.order = order-- rssArticle.order = order--
} }
App.db.rssArticleDao().insert(*it.toTypedArray()) App.db.rssArticleDao().insert(*list.toTypedArray())
if (!rssSource.ruleNextPage.isNullOrEmpty()) { if (!rssSource.ruleNextPage.isNullOrEmpty()) {
App.db.rssArticleDao().clearOld(url!!, order) App.db.rssArticleDao().clearOld(url!!, order)
withContext(Main) {
callBack?.loadFinally(true)
}
} else {
withContext(Main) {
callBack?.loadFinally(false)
}
} }
isLoading = false isLoading = false
} }
}.onError { }.onError {
toast(it.localizedMessage) toast(it.localizedMessage)
@ -56,6 +68,27 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application
} }
} }
fun loadMore() {
isLoading = true
val source = rssSource
val pageUrl = nextPageUrl
if (source != null && pageUrl != null) {
Rss.getArticles(source, pageUrl)
.onSuccess(IO) {
nextPageUrl = it?.nextPageUrl
it?.articles?.let { list ->
list.forEach { rssArticle ->
rssArticle.order = order--
}
App.db.rssArticleDao().insert(*list.toTypedArray())
isLoading = false
}
}
} else {
callBack?.loadFinally(false)
}
}
fun read(rssArticle: RssArticle) { fun read(rssArticle: RssArticle) {
execute { execute {
rssArticle.read = true rssArticle.read = true
@ -76,6 +109,6 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application
interface CallBack { interface CallBack {
var adapter: RssArticlesAdapter var adapter: RssArticlesAdapter
fun loadFinally() fun loadFinally(hasMore: Boolean)
} }
} }
Loading…
Cancel
Save