Reputation: 63
I am currently creating an app with Horizontal Pager in JetPack Compose as below
@ExperimentalAnimationApi
@ExperimentalPagerApi // HorizontalPager is experimental
@Composable
fun HorizontalPages(
lstQuestions: List<CertQuestions>,
lstOptions: List<CertAnswers>,
mainDataViewModel: MainDataViewModel,
pagerState: PagerState,
modifier: Modifier = Modifier
) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize()
) { page ->
val certQuestions = lstQuestions[page]
val lstOptionsFiltered: List<CertAnswers> = lstOptions.filter { lstQuestions.map { certQuestions.question_id } .contains(it.question_id) }
val lst: List<CertAnswers> =
lstOptionsFiltered.filter { it.question_id == certQuestions.question_id }.toList()
QueryCardPager(query = certQuestions, lstOptions = lst, mainDataViewModel= mainDataViewModel , pageNumber = page+1, pageCount = lstQuestions.size)
}
}
The listQuestion in the above is basically a shuffled list after I retrieve it from DB based on an condition.
when (val result = mainDataViewModel.quState.collectAsState().value) {
is QueryState.Error -> {
Log.d("Error", "Error Occured")
}
is QueryState.Success -> {
lstQuestions = result.queries
lstQuestions = when (filter) {
"pass" -> {
lstQuestions.filter { it.knowAnswer }.shuffled()
}
"new" -> {
lstQuestions.filter { !it.knowAnswer }.shuffled()
}
"random25" -> {
lstQuestions.shuffled().take(25)
}
"random65" -> {
lstQuestions.shuffled().take(65)
}
else -> {
lstQuestions.shuffled()
}
}
}
}
In the Card View,I am calling a ViewModel Data Update Method, which basically sends a updated boolean variable to DB.
@ExperimentalAnimationApi
@Composable
fun QueryCardPager(query: CertQuestions,
lstOptions: List<CertAnswers>,
mainDataViewModel: MainDataViewModel,
pageNumber : Int,
pageCount : Int,
){
.
.
.
IconButton(
onClick = {
mainDataViewModel.updateKnowAnswer(query.question_id, !query.knowAnswer)
}
) {
Icon(
imageVector = if (query.knowAnswer) Icons.Filled.DoneAll
else Icons.Filled.Done,
contentDescription = null,
tint = if (query.knowAnswer) Color.Blue else Color.Gray
)
}
}
ViewModel
private val _quState = MutableStateFlow<QueryState>(QueryState.Loading)
private val _optState = MutableStateFlow<OptionsState>(OptionsState.Loading)
// UI collects from this StateFlow to get it"s state update
val quState = _quState.asStateFlow()
val optState = _optState.asStateFlow()
fun getQuestions() = viewModelScope.launch {
try {
certsRepository.getAllQuestions().distinctUntilChanged().collect(){ result->
if(result.isEmpty()){
_quState.value =QueryState.Empty
}else
{
_quState.value = QueryState.Success(result)
//questionsData.value = result
}
}
}catch (e: Exception){
_quState.value = QueryState.Error(exception = e)
}
}
The problem is after I call the updateKnowAnswer method, it works for sometime. and when it work, the list is refreshed again and a new shuffled list is loaded. How to save the list and whether I am calling the update method in a right way.
Upvotes: 0
Views: 3153
Reputation: 88072
You need to save ids after shuffle
and reuse them on the next time. I suggest you moving this login to the view model too, like this:
private val _filter = MutableStateFlow("pass")
val filter: Flow<String> = _filter
fun updateFilter(filter: String) {
_filter.value = filter
}
private var savedRandomIds = mutableMapOf<String, List<QueryId>>()
val lstQuestions: Flow<List<Query>> = quState.combine(_filter) { result, filter ->
when (result) {
is QueryState.Error -> {
Log.d("Error", "Error Occured")
listOf()
}
is QueryState.Success -> {
val savedIds = savedRandomIds[filter]
if (savedIds != null) {
result.queries.filter { savedIds.contains(it.id) }
} else {
when (filter) {
"pass" -> {
result.queries
.filter { it.knowAnswer }
.shuffled()
}
"new" -> {
result.queries.filter { !it.knowAnswer }.shuffled()
}
"random25" -> {
result.queries.shuffled().take(25)
}
"random65" -> {
result.queries.shuffled().take(65)
}
else -> {
result.queries.shuffled()
}
}.also { shuffled ->
savedRandomIds[filter] = shuffled.map { it.id }
}
}
}
}
}
In your composable collect lstQuestions
instead of quState
:
mainDataViewModel.lstQuestions.collectAsState(listOf())
Upvotes: 0