Hey I am working on unlimited data with Viewpager 2 and Paging 3 library. I successfully created the logic to create unlimited pages by the help of paging source. I am swiping single pages by buttons in both direction.
Video Link to watch :- Youtube Video
Github Source: - ViewPager Repository
Problem what I am getting
When i click slowly on previous button it swipe single page, but if i click quickly multiple times on previous button it start scrolling more than we click and it's not stopping until we click on viewpager. It's kind of race condition.
I asked in issue tracker, they suggested me to use itemBefore and itemAfter IssueTracker. I implemented this, but i failed to achieve good outcome.
MainActivity.kt
package com.example.viewpagerexample
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.example.viewpagerexample.databinding.ActivityMainBinding
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private val viewModel by viewModels<ViewPagerViewModel>()
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ViewPagerAdapter()
lifecycleScope.launch {
viewModel.dataList.collectLatest {
adapter.submitData(it)
}
}
binding.viewpager.adapter = adapter
binding.next.setOnClickListener {
binding.viewpager.setCurrentItem(binding.viewpager.currentItem.plus(1), true)
}
binding.previous.setOnClickListener {
binding.viewpager.setCurrentItem(binding.viewpager.currentItem.minus(1), true)
}
}
}
ViewPagerDataSource.kt
package com.example.viewpagerexample
import android.util.Log
import java.util.*
class ViewPagerDataSource(
private val pageSize: Int,
private val currentDate: Date
) {
fun loadDataSource(pageNumber: Int): List<Date> {
val dates = mutableListOf<Date>()
val startingDate = startingDate(pageNumber)
val tempCalendar = Calendar.getInstance()
tempCalendar.time = startingDate
Log.e("loadData startingDate", "" + startingDate)
var index = 0;
while (index++ < pageSize) {
dates.add(tempCalendar.time)
tempCalendar.add(Calendar.DATE, 1)
}
return dates
}
private fun startingDate(pageNumber: Int): Date {
Calendar.getInstance().let {
it.time = currentDate
it.add(Calendar.DATE, (pageNumber * pageSize) + pageSize)
return it.time
}
}
}
ViewPagerPagingSource.kt
This is my paging source and i don't get how to use itembefore and itemAfter in my condition. Also I didn't get getRefreshKey what is the use of this? If i pass null is it fine for that or what else do I need to pass.
package com.example.viewpagerexample
import androidx.paging.PagingSource
import androidx.paging.PagingState
import java.io.IOException
import java.util.*
class ViewPagerPagingSource(
private val dataSource: ViewPagerDataSource
) : PagingSource<Int, Date>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Date> {
val position = params.key ?: 0
return try {
val data = dataSource.loadDataSource(position)
LoadResult.Page(
data = data,
prevKey = if (data.isEmpty()) null else position - 1,
nextKey = if (data.isEmpty()) null else position + 1,
itemsBefore = LoadResult.Page.COUNT_UNDEFINED,
itemsAfter = LoadResult.Page.COUNT_UNDEFINED
)
} catch (exception: IOException) {
LoadResult.Error(exception)
}
}
override fun getRefreshKey(state: PagingState<Int, Date>): Int? {
return null
}
}
ViewPagerViewModel.kt
package com.example.viewpagerexample
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.paging.Pager
import androidx.paging.PagingConfig
import java.util.*
class ViewPagerViewModel(app: Application) : AndroidViewModel(app) {
private val dataSource = ViewPagerDataSource(10, currentDate())
val dataList =
Pager(config = PagingConfig(
pageSize = 10,
enablePlaceholders = true
), pagingSourceFactory = {
ViewPagerPagingSource(dataSource)
}).flow
private fun currentDate(): Date {
val calendar = Calendar.getInstance()
return calendar.time
}
}
Adapter and Holder are attached in Github Link please find if you need them.
build.Gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.viewpagerexample"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation "androidx.paging:paging-runtime-ktx:3.0.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation 'androidx.fragment:fragment-ktx:1.3.6'
//noinspection GradleDynamicVersion
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
from How to use itemAfter or itemBefore in PagingSource LoadResult Page Paging 3
No comments:
Post a Comment