Kotlin项目实战之手机影音---解析首页数据绑定列表、列表条目view更新、首页下拉刷新处理、上拉加载更多

解析首页数据绑定列表:

接着上一次https://www.cnblogs.com/webor2006/p/12909992.html的功能继续开练,在上一次已经将首页的列表数据请求下来了,先贴一下返回的数据JSON:

{
    "songlist":[
        {
            "artist_id":"19165",
            "all_artist_ting_uid":"7988",
            "all_artist_id":"19165",
            "language":"\u82f1\u8bed",
            "publishtime":"2017-04-26",
            "album_no":"17",
            "versions":"",
            "pic_big":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_150,h_150",
            "pic_small":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_90,h_90",
            "country":"\u6b27\u7f8e",
            "area":"2",
            "lrclink":"",
            "hot":"0",
            "file_duration":"0",
            "del_status":"0",
            "resource_type":"0",
            "resource_type_ext":"2",
            "copy_type":"1",
            "relate_status":"0",
            "all_rate":"",
            "has_mv_mobile":0,
            "toneid":"0",
            "bitrate_fee":"{\"0\":\"129|-1\",\"1\":\"-1|-1\"}",
            "biaoshi":"vip,perm-1",
            "info":"",
            "has_filmtv":"0",
            "si_proxycompany":"\u770b\u89c1\u7f51\u7edc\u79d1\u6280\uff08\u4e0a\u6d77\uff09\u6709\u9650\u516c\u53f8",
            "song_id":"677470939",
            "title":"Wonderful Tonight",
            "ting_uid":"7988",
            "author":"Damage",
            "album_id":"677470905",
            "album_title":"Forever",
            "is_first_publish":0,
            "havehigh":0,
            "charge":0,
            "has_mv":0,
            "learn":0,
            "song_source":"web",
            "piao_id":"0",
            "korean_bb_song":"0",
            "mv_provider":"0000000000",
            "listen_total":"0",
            "pic_radio":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_300,h_300",
            "pic_s500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_premium":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_huge":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000",
            "album_500_500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "album_800_800":"",
            "album_1000_1000":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000"
        },
        {
            "artist_id":"19165",
            "all_artist_ting_uid":"7988",
            "all_artist_id":"19165",
            "language":"\u82f1\u8bed",
            "publishtime":"2017-04-26",
            "album_no":"16",
            "versions":"",
            "pic_big":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_150,h_150",
            "pic_small":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_90,h_90",
            "country":"\u6b27\u7f8e",
            "area":"2",
            "lrclink":"",
            "hot":"0",
            "file_duration":"0",
            "del_status":"0",
            "resource_type":"0",
            "resource_type_ext":"2",
            "copy_type":"1",
            "relate_status":"0",
            "all_rate":"",
            "has_mv_mobile":0,
            "toneid":"0",
            "bitrate_fee":"{\"0\":\"129|-1\",\"1\":\"-1|-1\"}",
            "biaoshi":"vip,perm-1",
            "info":"",
            "has_filmtv":"0",
            "si_proxycompany":"\u770b\u89c1\u7f51\u7edc\u79d1\u6280\uff08\u4e0a\u6d77\uff09\u6709\u9650\u516c\u53f8",
            "song_id":"677470938",
            "title":"Love II Love",
            "ting_uid":"7988",
            "author":"Damage",
            "album_id":"677470905",
            "album_title":"Forever",
            "is_first_publish":0,
            "havehigh":0,
            "charge":0,
            "has_mv":0,
            "learn":0,
            "song_source":"web",
            "piao_id":"0",
            "korean_bb_song":"0",
            "mv_provider":"0000000000",
            "listen_total":"0",
            "pic_radio":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_300,h_300",
            "pic_s500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_premium":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_huge":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000",
            "album_500_500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "album_800_800":"",
            "album_1000_1000":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000"
        },
        {
            "artist_id":"19165",
            "all_artist_ting_uid":"7988",
            "all_artist_id":"19165",
            "language":"\u82f1\u8bed",
            "publishtime":"2017-04-26",
            "album_no":"15",
            "versions":"",
            "pic_big":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_150,h_150",
            "pic_small":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_90,h_90",
            "country":"\u6b27\u7f8e",
            "area":"2",
            "lrclink":"",
            "hot":"0",
            "file_duration":"0",
            "del_status":"0",
            "resource_type":"0",
            "resource_type_ext":"2",
            "copy_type":"1",
            "relate_status":"0",
            "all_rate":"",
            "has_mv_mobile":0,
            "toneid":"0",
            "bitrate_fee":"{\"0\":\"129|-1\",\"1\":\"-1|-1\"}",
            "biaoshi":"vip,perm-1",
            "info":"",
            "has_filmtv":"0",
            "si_proxycompany":"\u770b\u89c1\u7f51\u7edc\u79d1\u6280\uff08\u4e0a\u6d77\uff09\u6709\u9650\u516c\u53f8",
            "song_id":"677470937",
            "title":"Love Guaranteed",
            "ting_uid":"7988",
            "author":"Damage",
            "album_id":"677470905",
            "album_title":"Forever",
            "is_first_publish":0,
            "havehigh":0,
            "charge":0,
            "has_mv":0,
            "learn":0,
            "song_source":"web",
            "piao_id":"0",
            "korean_bb_song":"0",
            "mv_provider":"0000000000",
            "listen_total":"0",
            "pic_radio":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_300,h_300",
            "pic_s500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_premium":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_huge":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000",
            "album_500_500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "album_800_800":"",
            "album_1000_1000":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000"
        },
        {
            "artist_id":"19165",
            "all_artist_ting_uid":"7988",
            "all_artist_id":"19165",
            "language":"\u82f1\u8bed",
            "publishtime":"2017-04-26",
            "album_no":"14",
            "versions":"",
            "pic_big":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_150,h_150",
            "pic_small":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_90,h_90",
            "country":"\u6b27\u7f8e",
            "area":"2",
            "lrclink":"",
            "hot":"0",
            "file_duration":"0",
            "del_status":"0",
            "resource_type":"0",
            "resource_type_ext":"2",
            "copy_type":"1",
            "relate_status":"0",
            "all_rate":"",
            "has_mv_mobile":0,
            "toneid":"0",
            "bitrate_fee":"{\"0\":\"129|-1\",\"1\":\"-1|-1\"}",
            "biaoshi":"vip,perm-1",
            "info":"",
            "has_filmtv":"0",
            "si_proxycompany":"\u770b\u89c1\u7f51\u7edc\u79d1\u6280\uff08\u4e0a\u6d77\uff09\u6709\u9650\u516c\u53f8",
            "song_id":"677470936",
            "title":"Forever",
            "ting_uid":"7988",
            "author":"Damage",
            "album_id":"677470905",
            "album_title":"Forever",
            "is_first_publish":0,
            "havehigh":0,
            "charge":0,
            "has_mv":0,
            "learn":0,
            "song_source":"web",
            "piao_id":"0",
            "korean_bb_song":"0",
            "mv_provider":"0000000000",
            "listen_total":"0",
            "pic_radio":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_300,h_300",
            "pic_s500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_premium":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_huge":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000",
            "album_500_500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "album_800_800":"",
            "album_1000_1000":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000"
        },
        {
            "artist_id":"19165",
            "all_artist_ting_uid":"7988",
            "all_artist_id":"19165",
            "language":"\u82f1\u8bed",
            "publishtime":"2017-04-26",
            "album_no":"13",
            "versions":"",
            "pic_big":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_150,h_150",
            "pic_small":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_90,h_90",
            "country":"\u6b27\u7f8e",
            "area":"2",
            "lrclink":"",
            "hot":"0",
            "file_duration":"0",
            "del_status":"0",
            "resource_type":"0",
            "resource_type_ext":"2",
            "copy_type":"1",
            "relate_status":"0",
            "all_rate":"",
            "has_mv_mobile":0,
            "toneid":"0",
            "bitrate_fee":"{\"0\":\"129|-1\",\"1\":\"-1|-1\"}",
            "biaoshi":"vip,perm-1",
            "info":"",
            "has_filmtv":"0",
            "si_proxycompany":"\u770b\u89c1\u7f51\u7edc\u79d1\u6280\uff08\u4e0a\u6d77\uff09\u6709\u9650\u516c\u53f8",
            "song_id":"677470935",
            "title":"In Your Eyes\/ One Last Time",
            "ting_uid":"7988",
            "author":"Damage",
            "album_id":"677470905",
            "album_title":"Forever",
            "is_first_publish":0,
            "havehigh":0,
            "charge":0,
            "has_mv":0,
            "learn":0,
            "song_source":"web",
            "piao_id":"0",
            "korean_bb_song":"0",
            "mv_provider":"0000000000",
            "listen_total":"0",
            "pic_radio":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_300,h_300",
            "pic_s500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_premium":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "pic_huge":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000",
            "album_500_500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_500,h_500",
            "album_800_800":"",
            "album_1000_1000":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/01bfbcfef0c7bc15245cc55ed0b7d4b9\/677470940\/677470940.jpg@s_2,w_1000,h_1000"
        }],
    "songnums":"77",
    "havemore":1,
    "artistinfo":{
        "ting_uid":"7988",
        "name":"Damage",
        "aliasname":"",
        "translatename":"",
        "firstchar":"D",
        "gender":"2",
        "area":"2",
        "country":"\u82f1\u56fd",
        "avatar_big":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/A4DB0C2ED8836FA12D1DFC8195292371\/252341874\/252341874.jpg@s_2,w_240,h_240",
        "avatar_middle":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/A4DB0C2ED8836FA12D1DFC8195292371\/252341874\/252341874.jpg@s_2,w_120,h_120",
        "avatar_small":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/A4DB0C2ED8836FA12D1DFC8195292371\/252341874\/252341874.jpg@s_2,w_48,h_48",
        "avatar_mini":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/A4DB0C2ED8836FA12D1DFC8195292371\/252341874\/252341874.jpg@s_2,w_20,h_20",
        "constellation":"\u672a\u77e5",
        "stature":" 0.00",
        "weight":" 0.00",
        "bloodtype":"\u672a\u77e5",
        "company":"\u767e\u4ee3\u5531\u7247\uff08EMI MUSIC\uff09",
        "intro":"Damage\u662f\u6765\u81ea\u82f1\u56fd\u7684R&Bs\u4e50\u961f\u300290\u5e74\u4ee3,\u4ed6\u4eec\u768410\u9996\u5355\u66f2\u53d6\u5f97\u8fc7\u5de8\u5927\u7684\u6210\u529f,\u4f46\u51fa\u9053\u4ee5\u6765\u4ec5\u53d1\u884c\u4e86\u4e24\u5f20\u4e13\u8f91\u3002\u9996\u5f20\u540c\u540d\u4e13\u8f91\u53d1\u884c\u4e8e1997\u5e74,\u5355\u66f2Love Guaranteed\u548cWonderful Tonight\u4f4d\u5c45\u699c\u5355\u7b2c10\u4f4d,\u4e4b\u540e\u5347\u5230\u7b2c3\u4f4d\u3002\u7b2c\u4e8c\u5f20\u4e13\u8f91Since You ve Been Gone \u4e8e2001\u5e74\u53d1\u884c\u3002\u4e4b\u540e\u4e50\u961f\u5f88\u5c11\u6709\u6d3b\u52a8\u3002",
        "albums_total":"6",
        "songs_total":"77",
        "birth":"0000-00-00",
        "url":"http:\/\/music.baidu.com\/artist\/7988",
        "del_status":"0",
        "artist_id":"19165",
        "source":"web",
        "avatar_s180":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/A4DB0C2ED8836FA12D1DFC8195292371\/252341874\/252341874.jpg@s_2,w_180,h_180",
        "avatar_s500":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/A4DB0C2ED8836FA12D1DFC8195292371\/252341874\/252341874.jpg@s_2,w_500,h_500",
        "avatar_s1000":"http:\/\/qukufile2.qianqian.com\/data2\/pic\/A4DB0C2ED8836FA12D1DFC8195292371\/252341874\/252341874.jpg",
        "piao_id":"0"
    },
    "error_code":22000
}

下面则来将它解析一下,先来定义好要转换的JSON实体,这里还是可以借助于插件来生成,如下:

这里删除了一些不重要的,如下:

package com.itheima.player.model.bean

/**
 * home界面每个条目的bean
 */
data class HomeBean(
    val songlist: List<HomeItemBean>
)

data class HomeItemBean(
    val albums_total: String,
    val aliasname: String,
    val area: String,
    val artist_id: String,
    val avatar_big: String,
    val avatar_middle: String,
    val avatar_mini: String,
    val avatar_s1000: String,
    val avatar_s180: String,
    val avatar_s500: String,
    val avatar_small: String,
    val birth: String,
    val bloodtype: String,
    val company: String,
    val constellation: String,
    val country: String,
    val del_status: String,
    val firstchar: String,
    val gender: String,
    val intro: String,
    val name: String,
    val piao_id: String,
    val songs_total: String,
    val source: String,
    val stature: String,
    val ting_uid: String,
    val translatename: String,
    val url: String,
    val weight: String,
    val title: String,
    val author: String,
    val album_500_500: String
)

其中Koltin的数据类可以参考https://www.cnblogs.com/webor2006/p/11234941.html,它就比Java的实体类要简洁清爽很多,木有大量的getter和setter所充斥着,好,接下来则需要使用gson来对其数据进行转换,先添加gson的依赖:

接下来运行看一下:

接下来则需要将其数据绑定到列表上:

接下来则来设置一下Adapter中的数据,不过在设置之前先要切换一下UI,因为OkHttp中回调是在子线程,咱们目前还没有用上RxAndroid,所以得显示的处理一下,这里封装一下,待未来进行复用:

package com.kotlin.musicplayer.utils

import android.os.Handler
import android.os.Looper


object ThreadUtil {
    val handler = Handler(Looper.getMainLooper());

    /**
     * 运行在主线程中
     */
    fun runOnMainThread(runnable: Runnable) {
        handler.post(runnable)
    }

}

好,接下来则可以来调用了,不过目前的adapter声明的是一个局部变量,需要提出来:

package com.kotlin.musicplayer.ui.fragment

import android.view.View
import android.webkit.WebSettings
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.itheima.player.model.bean.HomeBean
import com.kotlin.musicplayer.MyApplication
import com.kotlin.musicplayer.R
import com.kotlin.musicplayer.adapter.HomeAdapter
import com.kotlin.musicplayer.base.BaseFragment
import com.kotlin.musicplayer.utils.ThreadUtil
import com.kotlin.musicplayer.utils.URLProviderUtils
import kotlinx.android.synthetic.main.fragment_home.*
import okhttp3.*
import java.io.IOException

/**
 * 首页
 */
class HomeFragment : BaseFragment() {

    val adapter by lazy { HomeAdapter() }

    override fun initView(): View? {
        return View.inflate(context, R.layout.fragment_home, null)
    }

    override fun initListeners() {
        super.initListeners()
        recyclerView.layoutManager = LinearLayoutManager(context)
        recyclerView.adapter = adapter
    }

    override fun initData() {
        super.initData()
        loadDatas()
    }

    private fun loadDatas() {
        val path = URLProviderUtils.getHomeUrl(0, 5)
        val client = OkHttpClient()
        val request = Request.Builder()
            .get()
            .url(path)
            .addHeader("User-Agent", WebSettings.getDefaultUserAgent(MyApplication.instance))
            .build()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                showToast("获取数据出错")
            }

            override fun onResponse(call: Call, response: Response) {
                showToast("获取数据成功!")
                val result = response?.body?.string()
                val gson = Gson()
                val list = gson.fromJson<HomeBean>(
                    result,
                    object : TypeToken<HomeBean>() {}.type
                )
                println("获取数据成功 list:" + list.songlist.size)
                ThreadUtil.runOnMainThread(object : Runnable {
                    override fun run() {
                        adapter.setData(list.songlist)
                    }
                });
            }

        })
    }
}

列表条目view更新:

接下来则需要根据绑定的数据源来刷新列表界面,这块属于Android的基础,就不过多解释了,比较简单:

package com.kotlin.musicplayer.adapter

import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.itheima.player.model.bean.HomeItemBean
import com.kotlin.musicplayer.ui.widget.HomeItemView

/**
 * 首页列表Adapter
 */
class HomeAdapter : RecyclerView.Adapter<HomeAdapter.HomeHolder>() {
    private var list = ArrayList<HomeItemBean>()

    fun setData(list: List<HomeItemBean>) {
        this.list.clear()
        this.list.addAll(list);
        notifyDataSetChanged()
    }

    class HomeHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeHolder {
        return HomeHolder(HomeItemView(parent?.context))
    }

    override fun getItemCount(): Int {
        return list.size
    }

    override fun onBindViewHolder(holder: HomeHolder, position: Int) {
        val data = list.get(position)
        val itemView = holder.itemView as HomeItemView
        itemView.setData(data)
    }
}

这里有个Koltin的知识点,就是强转类型得要用as:

package com.kotlin.musicplayer.ui.widget

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.RelativeLayout
import com.itheima.player.model.bean.HomeItemBean
import com.kotlin.musicplayer.R
import kotlinx.android.synthetic.main.item_home.view.*

class HomeItemView : RelativeLayout {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    init {
        View.inflate(context, R.layout.item_home, this)
    }

    /**
     * 刷新条目view数据
     */
    fun setData(data: HomeItemBean) {
        //歌曲名称
        tv_title.setText(data.title)
        //简介
        tv_desc.setText(data.author)
        //背景图片
    }
}

而背景图的加载得依赖三方的框架,这里采用Picasso:

运行:

首页下拉刷新处理:

接下来则来处理下拉刷新的功能,这块也是通用Android的处理,不多说,重点是体会Kotlin开发的编码方式:

先用下拉刷新的控制包裹一下:

此时就已经有下拉的效果了:

接下来则需要来处理刷新的逻辑,不过在处理它之前,先来对刷新转圈的增加一点色彩,目前黑色不太好看:

那咱们设置三个颜色看看:

此时再看一下效果:

三种颜色交替变幻,精彩多了,接下来则开始处理刷新的逻辑:

此时又来回顾一下Kotlin的知识点,通过做项目来不断的加强对Kotlin基础知识的回顾这样慢慢这门语言的掌握就渗透在你的脑海当中成为自己的技能知识树上的一部分了,啰嗦一点没关系,掌握才是重点,啥知识点呢?

这是因为如果它接收的是一个Lambda表达式则就可以直接用这种方式,而刚好这个回调接口就只定义一个方法,满足Lambda表达式的语法:

接下来在加载回调后则需要停止刷新,所以处理如下:

运行:

上拉加载更多:

完成了下拉刷新之后,配合的列表经典动作当然少不了有上拉分页加载喽,这块就稍麻烦一些,不过Android的列表分页套路基本差不多,也不难,这块也不过多解释,下面开始实现:

由于在列表中要增加一个底部loading的列表项,所以,先来对这块+1:

接下来则来准备一个加载项的View:

package com.kotlin.musicplayer.ui.widget

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.RelativeLayout
import com.kotlin.musicplayer.R


/**
 * 列表加载更多项
 */
class LoadMoreView : RelativeLayout {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    init {
        View.inflate(context, R.layout.view_loadmore, this)
    }
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="10dp">

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

接下来则给Adapter中来增加2种类型的条目,如下:

然后根据咱们设定的条目的类型来创建ViewHolder:

package com.kotlin.musicplayer.adapter

import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.itheima.player.model.bean.HomeItemBean
import com.kotlin.musicplayer.ui.widget.HomeItemView
import com.kotlin.musicplayer.ui.widget.LoadMoreView

/**
 * 首页列表Adapter
 */
class HomeAdapter : RecyclerView.Adapter<HomeAdapter.HomeHolder>() {
    private var list = ArrayList<HomeItemBean>()

    fun setData(list: List<HomeItemBean>) {
        this.list.clear()
        this.list.addAll(list);
        notifyDataSetChanged()
    }

    class HomeHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeHolder {
        if (viewType == 1) {
            //最后一条
            return HomeHolder(LoadMoreView(parent?.context))
        } else {
            //普通条目
            return HomeHolder(HomeItemView(parent?.context))
        }
    }

    override fun getItemViewType(position: Int): Int {
        if (position == list.size) {
            //最后一条,则显示加载更多
            return 1
        } else {
            //普通条目
            return 0
        }
    }

    override fun getItemCount(): Int {
        return list.size + 1
    }

    override fun onBindViewHolder(holder: HomeHolder, position: Int) {
        //如果是最后一条 不需要刷新view
        if (position == list.size) return
        val data = list.get(position)
        val itemView = holder.itemView as HomeItemView
        itemView.setData(data)
    }
}

运行看一下有木有下滑至最后有loading的效果:

接下来则来处理分页的逻辑,肯定得要监听列表的状态了,代码贴出来:

package com.kotlin.musicplayer.ui.fragment

import android.graphics.Color
import android.view.View
import android.webkit.WebSettings
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.itheima.player.model.bean.HomeBean
import com.kotlin.musicplayer.MyApplication
import com.kotlin.musicplayer.R
import com.kotlin.musicplayer.adapter.HomeAdapter
import com.kotlin.musicplayer.base.BaseFragment
import com.kotlin.musicplayer.utils.ThreadUtil
import com.kotlin.musicplayer.utils.URLProviderUtils
import kotlinx.android.synthetic.main.fragment_home.*
import okhttp3.*
import java.io.IOException

/**
 * 首页
 */
class HomeFragment : BaseFragment() {

    val adapter by lazy { HomeAdapter() }

    override fun initView(): View? {
        return View.inflate(context, R.layout.fragment_home, null)
    }

    override fun initListeners() {
        super.initListeners()
        recyclerView.layoutManager = LinearLayoutManager(context)
        recyclerView.adapter = adapter
        //监听列表滑动
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    //是否最后一条已经显示
                    val layoutManager = recyclerView.layoutManager
                    if (layoutManager is LinearLayoutManager) {
                        //由于RecycleView还有其它样式的列表,所以这里只有下拉列表类型才处理分页
                        val manager: LinearLayoutManager = layoutManager
                        val lastPosition = manager.findLastVisibleItemPosition()
                        if (lastPosition == adapter.itemCount - 1) {
                            //开始加载更多数据
                            loadMoreDatas(adapter.itemCount - 1);
                        }
                    }
                }
            }
        })
        lay_refresh.setColorSchemeColors(Color.RED, Color.YELLOW, Color.BLUE)
        lay_refresh.setOnRefreshListener {
            loadDatas()
        }
    }

    override fun initData() {
        super.initData()
        loadDatas()
    }

    private fun loadMoreDatas(offset: Int) {
        val path = URLProviderUtils.getHomeUrl(offset, 5)
        val client = OkHttpClient()
        val request = Request.Builder()
            .get()
            .url(path)
            .addHeader("User-Agent", WebSettings.getDefaultUserAgent(MyApplication.instance))
            .build()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                showToast("获取数据出错")
                ThreadUtil.runOnMainThread(object : Runnable {
                    override fun run() {
                        lay_refresh.isRefreshing = false
                    }

                })
            }

            override fun onResponse(call: Call, response: Response) {
                showToast("获取数据成功!")
                val result = response?.body?.string()
                val gson = Gson()
                val list = gson.fromJson<HomeBean>(
                    result,
                    object : TypeToken<HomeBean>() {}.type
                )
                println("获取数据成功 list:" + list.songlist.size)
                ThreadUtil.runOnMainThread(object : Runnable {
                    override fun run() {
                        lay_refresh.isRefreshing = false
                        adapter.loadMoreData(list.songlist)
                    }
                });
            }

        })
    }

    private fun loadDatas() {
        val path = URLProviderUtils.getHomeUrl(0, 5)
        val client = OkHttpClient()
        val request = Request.Builder()
            .get()
            .url(path)
            .addHeader("User-Agent", WebSettings.getDefaultUserAgent(MyApplication.instance))
            .build()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                showToast("获取数据出错")
                ThreadUtil.runOnMainThread(object : Runnable {
                    override fun run() {
                        lay_refresh.isRefreshing = false
                    }

                })
            }

            override fun onResponse(call: Call, response: Response) {
                showToast("获取数据成功!")
                val result = response?.body?.string()
                val gson = Gson()
                val list = gson.fromJson<HomeBean>(
                    result,
                    object : TypeToken<HomeBean>() {}.type
                )
                println("获取数据成功 list:" + list.songlist.size)
                ThreadUtil.runOnMainThread(object : Runnable {
                    override fun run() {
                        lay_refresh.isRefreshing = false
                        adapter.setData(list.songlist)
                    }
                });
            }

        })
    }
}

运行看一下效果:

 

posted on 2020-06-25 13:46  cexo  阅读(653)  评论(0编辑  收藏  举报

导航