Hey I am working in Viewpager 2 with Paging library 3. I used viewpager 2 to show single date in page and doing increment/decrement by page swiping. I am passing current date in my current item of viewpager. I did this successfully without any problem. But sometimes when I open it adding extra page with wrong index number as my current item in viewpager. I am adding my youtube link. In video, I am clicking on button and opening next activity. Inside that I am implemented the viewpager + paging library. I am passing current date as [19/03/2022]. Sometimes it open correct page but sometimes my paging or viewpager loading [14/03/2022], extra page and open in wrong index number. You can see clearly in my video what I mean that.
Log in video
1st Time click
2022-03-19 15:07:38.094 7502-7502/com.example.viewpagerexample E/Page number: 0 ::-> [19/03/2022]
2022-03-19 15:07:38.232 7502-7502/com.example.viewpagerexample E/Page number: -1 ::-> [14/03/2022, 15/03/2022, 16/03/2022, 17/03/2022, 18/03/2022]
2nd Time Click
2022-03-19 15:07:40.226 7502-7502/com.example.viewpagerexample E/Page number: 0 ::-> [19/03/2022]
2022-03-19 15:07:40.255 7502-7502/com.example.viewpagerexample E/Page number: -1 ::-> [14/03/2022, 15/03/2022, 16/03/2022, 17/03/2022, 18/03/2022]
3rd Time Click
2022-03-19 15:07:42.692 7502-7502/com.example.viewpagerexample E/Page number: 0 ::-> [19/03/2022]
2022-03-19 15:07:42.731 7502-7502/com.example.viewpagerexample E/Page number: -1 ::-> [14/03/2022, 15/03/2022, 16/03/2022, 17/03/2022, 18/03/2022]
4th Time Click
2022-03-19 15:07:44.282 7502-7502/com.example.viewpagerexample E/Page number: 0 ::-> [19/03/2022]
2022-03-19 15:07:44.307 7502-7502/com.example.viewpagerexample E/Page number: -1 ::-> [14/03/2022, 15/03/2022, 16/03/2022, 17/03/2022, 18/03/2022]
5th Time Click
2022-03-19 15:07:46.713 7502-7502/com.example.viewpagerexample E/Page number: 0 ::-> [19/03/2022]
2022-03-19 15:07:46.738 7502-7502/com.example.viewpagerexample E/Page number: -1 ::-> [14/03/2022, 15/03/2022, 16/03/2022, 17/03/2022, 18/03/2022]
6th Time click you can see it added extra page with wrong index in my viewpager.
2022-03-19 15:07:48.962 7502-7502/com.example.viewpagerexample E/Page number: 0 ::-> [19/03/2022]
2022-03-19 15:07:48.984 7502-7502/com.example.viewpagerexample E/Page number: -1 ::-> [14/03/2022, 15/03/2022, 16/03/2022, 17/03/2022, 18/03/2022]
2022-03-19 15:07:48.998 7502-7502/com.example.viewpagerexample E/Page number: -2 ::-> [09/03/2022, 10/03/2022, 11/03/2022, 12/03/2022, 13/03/2022]
You Can see same log in my youtube video.
MainActivity.kt
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_IDLE
import com.example.viewpagerexample.databinding.ActivityMainBinding
import kotlinx.coroutines.flow.collectLatest
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.launchWhenCreated {
viewModel.dataList.collectLatest {
adapter.submitData(it)
}
}
binding.viewpager.adapter = adapter
binding.next.setOnClickListener {
if (binding.viewpager.scrollState == SCROLL_STATE_IDLE) {
binding.viewpager.setCurrentItem(binding.viewpager.currentItem.plus(1), true)
}
}
binding.previous.setOnClickListener {
if (binding.viewpager.scrollState == SCROLL_STATE_IDLE) {
binding.viewpager.setCurrentItem(binding.viewpager.currentItem.minus(1), true)
}
}
}
}
ViewPagerPagingSource.kt
import android.util.Log
import androidx.paging.PagingSource
import androidx.paging.PagingState
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
class ViewPagerPagingSource(
private val dataSource: DataSource
) : PagingSource<Int, Date>() {
private val format = SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Date> {
val position = params.key ?: 0
return try {
val data = dataSource.returnData(position)
Log.e("Page number", "$position ::-> ${data.result.map(format::format)}")
LoadResult.Page(
data = data.result,
prevKey = data.prevKey,
nextKey = data.nextKey
)
} catch (exception: IOException) {
LoadResult.Error(exception)
}
}
override fun getRefreshKey(state: PagingState<Int, Date>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
}
ViewPagerViewModel.kt
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) {
// pass current date as limit date
private val currentDateLimitDataSource = DataSource(size = 5, limitDate(), limitDate())
val dataList =
Pager(config = PagingConfig(
pageSize = 1
), pagingSourceFactory = {
ViewPagerPagingSource(currentDateLimitDataSource)
}).flow
private fun currentDate(): Date {
val calendar = Calendar.getInstance()
calendar.add(Calendar.DATE, -10)
return calendar.time
}
private fun limitDate(): Date {
val calendar = Calendar.getInstance()
return calendar.time
}
}
DataSource.kt
import java.util.*
class DataSource(
private val size: Int = 5,
private val currentDate: Date,
private val limitDate: Date? = null
) {
fun returnData(pageNumber: Int): Result {
val dateList = mutableListOf<Date>()
val startDateForPage = startDate(pageNumber)
val tempCalendar = Calendar.getInstance()
tempCalendar.time = startDateForPage
val lastDateForPage = endDate(startDateForPage)
var index = size
while (tempCalendar.time <= lastDateForPage && index-- > 0) {
dateList.add(tempCalendar.time)
tempCalendar.add(Calendar.DATE, 1)
}
return Result(
result = dateList,
pageNumber - 1,
if (lastDateForPage == limitDate)
null
else
pageNumber + 1
)
}
private fun startDate(pageNumber: Int): Date {
Calendar.getInstance().let {
it.time = currentDate
it.add(Calendar.DATE, pageNumber * size)
return it.time
}
}
private fun endDate(firstDateForPage: Date): Date? {
Calendar.getInstance().let {
it.time = firstDateForPage
it.add(Calendar.DATE, size)
limitDate?.let { limit ->
return if (it.time > limit) limit else it.time
} ?: run {
return it.time
}
}
}
data class Result(
val result: MutableList<Date>,
val prevKey: Int?,
val nextKey: Int?
)
}
My whole source code Github
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation "androidx.paging:paging-runtime-ktx:3.1.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1"
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation 'androidx.fragment:fragment-ktx:1.4.1'
//noinspection GradleDynamicVersion
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
from Unexpected behaviour on indexing in paging library 3
No comments:
Post a Comment