主要是Ptt一页的文章最多列出20篇,若要搜寻到20篇以前的文章就需要换页,幸运的是文章列表这边换页的指令蛮简单的。
可以看到在这边可以简单的用"P"和"N"换页。
实作上首先在SearchArticleResultAdapter新增callback来通知更新
//...
var needMoreArticleCallback: (() -> Unit)? = null
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindView(articleList[position])
if (position == articleList.size - 1 && articleList[position].number != "1") {
needMoreArticleCallback?.invoke()
}
}
//...
如果目前列表的最後一项编号不是1的话代表还有旧的内容,此时呼叫通知更新的方法。
//...
articleAdapter.needMoreArticleCallback = {
if (PttClient.getInstance().expect(inBoardPattern) == 2) {
(requireActivity() as MainActivity).showLoading("")
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
val ret = withContext(Dispatchers.IO) {
PttClient.getInstance().send("P")
delay(200L)
PttClient.getInstance().expect(inBoardPattern)
}
if (ret == 2) {
parseBoardArticle(PttClient.getInstance().getScreen())
}
(requireActivity() as MainActivity).dismissLoading()
}
}
}
//...
首先先用inBoardPattern确认目前画面在看板内再送後续指令,如前面所述送出P後确认画面依旧在看板内就送入parseBoardArticle方法内了。
为了保留现有内容并在後面新增文章,对此方法作了一点修改。
private val articleList = mutableListOf<Article>()
private fun parseBoardArticle(result: String) {
val articlePattern =
Pattern.compile("([●]|[ ])*(?<no>[0-9]+)[ ].([0-9 X]+|爆)(?<date>../..)[ ](?<author>.*?)([\\s□转]|R:)+(?<title>.*)")
val rows = result.split("\n")
val currentArticleList = mutableListOf<Article>()
for (row in rows) {
val matcher = articlePattern.matcher(row)
if (matcher.find()) {
val article = Article(
matcher.group("no")?.trim(),
matcher.group("date")?.trim(),
matcher.group("author")?.trim(),
matcher.group("title")?.trim()
)
if (!articleList.any { it.number == article.number }) {
currentArticleList.add(0, article)
}
Log.d(mTag, "article=$article")
}
}
articleList.addAll(currentArticleList)
articleAdapter.setData(articleList)
}
首先将articleList提出成全域变数,在解析目前页面时另外宣告currentArticleList来储存,最後再加入到articleList中。过程中则是用any来找出目前解析出的文章编号是否已经被加入过了,这是因为若剩余未显示的文章篇数不到20篇的话,在切换页面後会用已显示过的文章来补足20篇的篇数,因此有重复的可能。
articleList除了这边使用到以外,再先前的搜寻操作前要注意先将内容清除掉,以避免重复。
private suspend fun searchDetailProcess(command: String): Boolean {
articleList.clear()
//...
}
private fun refreshSearch() {
articleList.clear()
//...
}
最後稍微看一下设置及更新资料的部分。
fun setData(newList: List<Article>) {
val result = DiffUtil.calculateDiff(ArticleDiffUtilCallbackImpl(articleList, newList))
articleList.clear()
articleList.addAll(newList)
result.dispatchUpdatesTo(this)
}
主要就是使用Android提供的DiffUtil来做更新,并实作DiffUtil.Callback。
class ArticleDiffUtilCallbackImpl(
private val oldList: List<Article>,
private val newList: List<Article>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size
override fun getNewListSize(): Int = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].number == newList[newItemPosition].number
}
}
<<: D20 - 用 Swift 和公开资讯,打造投资理财的 Apps { 移动平均线(MA线)实作.3 }
变数..装啊~再装啊~ | 一元 二元 ++ -- | 算术->数值 | 逻辑->T/...
想想距离去年参加铁人也过了一年了,记得当时我才刚到职大概满半年吧,到现在也一年半了,我发生了哪些变化...
在昨天我们谈完如何使用Azure Container Registry异地复写建立多份Contain...
(因为题目在分类上是MobileDevelopment,所以就义务性的来讲APP开发吧!) (以下部...