Android Paging 3 Flow or LiveData,kotlin(1)

Android Paging 3 Flow or LiveData,kotlin(1)

android {
    buildFeatures {
        viewBinding = true
    }
}



dependencies {
    def paging_version = "3.1.1"
    implementation "androidx.paging:paging-runtime:$paging_version"
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
}

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.get
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import androidx.paging.LoadState
import androidx.paging.cachedIn
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.launch


class MainActivity : AppCompatActivity() {
    companion object {
        val TAG = "my-test"
    }

    private val viewModel by lazy { ViewModelProvider(this).get<MainViewModel>() }
    private val myAdapter = MyAdapter()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.layoutManager = GridLayoutManager(this, 3).apply {
            orientation = GridLayoutManager.VERTICAL
        }

        recyclerView.adapter = myAdapter

        lifecycleScope.launch {
            MyDataFlow.getPagingData().cachedIn(viewModel.viewModelScope).collect() { pagingData ->
                myAdapter.submitData(pagingData)
            }
        }
     /**或者

        val liveData = MyDataFlow.getPagingData().cachedIn(viewModel.viewModelScope).asLiveData()
        liveData.observe(this) {
            myAdapter.submitData(lifecycle, it)
        }

     */


        myAdapter.addLoadStateListener {
            when (it.refresh) {
                is LoadState.NotLoading -> {
                    //recyclerView.visibility = View.VISIBLE
                    Log.d(TAG, "LoadState.NotLoading")
                }

                is LoadState.Loading -> {
                    //recyclerView.visibility = View.INVISIBLE
                    Log.d(TAG, "LoadState.Loading")
                }

                is LoadState.Error -> {
                    val state = it.refresh as LoadState.Error
                    Log.d(TAG, "LoadState.Error")
                }
            }
        }
    }

    class MainViewModel : ViewModel() {

    }
}

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

package my.application

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView

class MyAdapter : PagingDataAdapter<MyData, MyAdapter.ViewHolder>(COMPARATOR) {
    companion object {
        private val COMPARATOR = object : DiffUtil.ItemCallback<MyData>() {
            override fun areItemsTheSame(oldItem: MyData, newItem: MyData): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(oldItem: MyData, newItem: MyData): Boolean {
                return oldItem == newItem
            }
        }
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val page: TextView = itemView.findViewById(R.id.page)
        val in_page_pos: TextView = itemView.findViewById(R.id.in_page_pos)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val repo = getItem(position)
        if (repo != null) {
            holder.page.text = "page=${repo.page}"
            holder.in_page_pos.text = "${repo.inPagePos}/${repo.pageSize}"
        }
    }
}

<?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="120dp"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="centerInside"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/page"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/in_page_pos"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

import java.util.UUID

data class MyData(
    val id: UUID,
    val page: Int,
    val inPagePos: Int,
    val pageSize: Int
)

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

object MyDataFlow {
    private const val PAGE_SIZE = 50

    private val myLoadDataService = MyLoadDataService.create()

    fun getPagingData(): Flow<PagingData<MyData>> {
        return Pager(
            config = PagingConfig(
                initialLoadSize = PAGE_SIZE * 2, //程序启动第1次load的第1页忠数据的数量
                pageSize = PAGE_SIZE, //每一次分页加载的数量
                prefetchDistance = PAGE_SIZE * 5, //距离底部多少条时候启动预加载,若做到用户滑动无感知,可以将此值设置的大些,比如PAGE_SIZE的n倍。
                enablePlaceholders = true,
                maxSize = Int.MAX_VALUE
            ),
            pagingSourceFactory = { MyPagingDataSource(myLoadDataService) }
        ).flow
    }
}

import android.util.Log
import java.util.UUID

class MyLoadDataService {
    suspend fun loadData(page: Int, perPage: Int): ArrayList<MyData> {
        Log.d(MainActivity.TAG, "$page - $perPage")

        val items: ArrayList<MyData> = ArrayList()
        for (i in 1..perPage) {
            var r = MyData(UUID.randomUUID(), page, i, perPage)
            items.add(r)
        }

        return items
    }

    companion object {
        fun create(): MyLoadDataService {
            return MyLoadDataService()
        }
    }
}

import androidx.paging.PagingSource
import androidx.paging.PagingState

class MyPagingDataSource(private val myLoadDataService: MyLoadDataService) :
    PagingSource<Int, MyData>() {

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MyData> {
        return try {
            val page = params.key ?: 1 // set page 1 as default
            val pageSize = params.loadSize

            var repoItems: ArrayList<MyData> = myLoadDataService.loadData(page, pageSize)

            val prevKey = if (page > 1) page - 1 else null
            val nextKey = if (repoItems.isNotEmpty()) page + 1 else null
            LoadResult.Page(repoItems, prevKey, nextKey)
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState<Int, MyData>): Int? {
        return 0
    }
}

基于Android官方Paging Library的RecyclerView分页加载框架_android setmainthreadexecutor_zhangphil的博客-CSDN博客基于Android官方Paging Library的RecyclerView分页加载框架我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见附录文章1。现在再介绍一种RecyclerView分页加载框架:Android Paging Library。Android Paging Library是Android官方supporthttps://blog.csdn.net/zhangphil/article/details/78627332

猜你喜欢

转载自blog.csdn.net/zhangphil/article/details/130735753