使用compose ,paging3,jsoup实现分页加载双色球开奖数据

本篇文章实现的功能就是在页面上分页加载双色球全部开奖数据,看着很简单,实现起来却很困难,是我低估了它的难度,还是我并不适合做程序员??不过经过多天的努力,最终还是实现了,在此记录一下。
知识来源主要有两个:
1,Jetpack新成员,Paging3从吐槽到真香
2, Github开源项目:NewzCompose
其中,
“1” => LotteryRepository(),LotteryViewModel(),LotteryPagingSource(),LotteryData()
"2" => LotteryActivity(),LotteryCompose()

主要引用到的资源,其中需要注意的是jsoup,使用代理的话会引入失败,需要开vpn或者通过jar包的方式引入

    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha03' // viewModel()
    implementation 'androidx.activity:activity-compose:1.3.0-alpha04' // setContent()
    implementation "androidx.paging:paging-runtime:3.0.0-beta02"
    implementation "androidx.paging:paging-compose:1.0.0-alpha08"
    //jsoup
    implementation 'org.jsoup:jsoup:1.13.1'

LotteryActivity()

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.lazy.LazyColumn
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemsIndexed

class LotteryActivity : ComponentActivity() {

    private val lotteryViewModel: LotteryViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val lazyPagingItems: LazyPagingItems =
                lotteryViewModel.getData().collectAsLazyPagingItems()
            LazyColumn(reverseLayout=true) {
                itemsIndexed(lazyPagingItems) { _, item ->
                    LotteryItem(item!!)
                }
            }
        }
    }
}

LotteryCompose()

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

@Composable
fun LotteryItem(lottery: Lottery) {
    Box(
        modifier = Modifier
            .padding(start = 16.dp, top = 8.dp, bottom = 8.dp)
            .clickable(onClick = {})
    ) {
        Row(modifier = Modifier.fillMaxWidth()) {
            Column(
                modifier = Modifier.padding(start = 8.dp)
            ) {
                Text(
                    lottery.code,//开奖号码
                    style = TextStyle(color = Color.Black, fontSize = 16.sp),
                    modifier = Modifier.padding(end = 8.dp),
                    maxLines = 1
                )
            }
            Column(
                modifier = Modifier.padding(start = 8.dp)
            ) {
                Text(
                    lottery.issue,//期号
                    style = TextStyle(color = Color.Black, fontSize = 16.sp),
                    modifier = Modifier.padding(end = 8.dp),
                    maxLines = 1
                )
            }
        }
    }
}

LotteryData()

data class Lottery(
    val code :String,   //开奖号码
    val issue :String,//期号
) : Serializable

LotteryViewModel()

class LotteryViewModel : ViewModel() {
    fun getData(): Flow> {
        return LotteryRepository.getPagingData().cachedIn(viewModelScope)
    }
}

LotteryRepository()

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow

object LotteryRepository {

    private const val PAGE_SIZE = 50

    fun getPagingData(): Flow> {
        return Pager(
            config = PagingConfig(
                pageSize = PAGE_SIZE,
                prefetchDistance = PAGE_SIZE.div(20)
            ),
            pagingSourceFactory = { LotteryPagingSource() }
        ).flow
    }
}

LotteryPagingSource()

import androidx.paging.PagingSource
import androidx.paging.PagingState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.withContext
import love.matrix.lottory004.util.TimeUtils
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.select.Elements

class LotteryPagingSource : PagingSource() {

    private val year = TimeUtils.nowTime.substring(2, 4).toInt()//取年份最后两位 (2021 => 21)
    private val lotterys = MutableStateFlow>(listOf())

    override suspend fun load(params: LoadParams): LoadResult {

        val page = params.key ?: year//一个年度的开奖数据为一页
        val lotteryList: MutableList = mutableListOf()

        withContext(Dispatchers.IO) {
            val doc =
                //"https://datachart.500.com/ssq/history/newinc/history.php?start=21001&end=21200"
                Jsoup.connect(TARGET_URL + "?start=${page}001&end=${page}200").get()
            val element: Element = doc.getElementById("tdata")
            val elements: Elements = element.select("tr.t_tr1")
            elements.forEach { item ->
                val aaa: Elements = item.select("td")
                if (!aaa.isNullOrEmpty()) {
                    val bbb = Lottery(
                        code = aaa[1].text() + "," +
                                aaa[2].text() + "," +
                                aaa[3].text() + "," +
                                aaa[4].text() + "," +
                                aaa[5].text() + "," +
                                aaa[6].text() + "  " +
                                aaa[7].text(),
                        issue = aaa[0].text()
                    )
                    lotteryList.add(bbb)
                }
            }
            lotterys.value = lotteryList
        }

        return try {
            //使用了反转LazyColumn(reverseLayout=true),所以向上滑为nextKey
            val prevKey = null
            val nextKey = if (page > 3) page - 1 else null//"3"为2003年,双色球2003年开始的
            LoadResult.Page(
                data = lotterys.value,
                prevKey = prevKey,
                nextKey = nextKey,
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState): Int? {
        TODO("Not yet implemented")
    }

    companion object {
        const val TARGET_URL =
            "https://datachart.500.com/ssq/history/newinc/history.php"

        const val USER_AGENT =
            "{Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Mobile Safari/537.36"

    }
}

TimeUtils()

import android.util.Log
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
object TimeUtils {
    val nowTime: String
        get() {
            val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINESE)
            val date = Date(System.currentTimeMillis())
            return simpleDateFormat.format(date)
        }
}

完成后,感觉这些都是一些模版代码,没什么好说的,所以就不多说什么了。

你可能感兴趣的:(使用compose ,paging3,jsoup实现分页加载双色球开奖数据)