Hey I am learning stateflow in android kotlin. I am creating a reverse conversation calendar view with the help of reyclerview. In my mainactivity
there is one fragment
, and inside that I have reyclerview
. My goal to is doing paging stuff in my recyclerview so I am loading few months first than adding more and more data in my reyclerview by the help of this answer. I achieved it successfully. But the problem is when I reached the threshold and it trigger the new data . My whole list is refershed and it not being updated it removed previous data. I don't understand why this happening in MutableStateFlow and also I am new in this flow. My Github project link is here. Please guide me what I am doing wrong here. My Goal is to prepend the stateFlow data. Thanks
ConversationFragment.kt
class ConversationFragment(val customManager: CustomManager) : Fragment() {
companion object {
private const val DATA = "data"
fun create(
data: List<ConversationDate>,
customManager: CustomManager
): ConversationFragment {
val fragment = ConversationFragment(customManager)
val bundle = Bundle()
bundle.putParcelableArrayList(
DATA,
ArrayList<Parcelable>(data)
)
fragment.arguments = bundle
return fragment
}
}
private var _binding: ConversationFragmentLayoutBinding? = null
private val binding get() = _binding!!
private val visibleThreshold = 7
private var previousTotalItemCount = 0
private var loading = true
private val weeklyAdapter = ConversationWeeklyAdapter()
private val viewModel by viewModels<FragmentViewModel>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
setupViewModel()
_binding = ConversationFragmentLayoutBinding.inflate(inflater, container, false)
setupView()
return binding.root
}
private fun setupViewModel() {
viewModel.data = arguments?.getParcelableArrayList(DATA)
viewModel.startDate = customManager.startDate()
viewModel.endDate = customManager.endDate()
}
private fun setupView() {
viewModel.weeklyFormatData()
activity?.lifecycleScope?.launchWhenCreated {
activity?.repeatOnLifecycle(Lifecycle.State.CREATED) {
viewModel.prepareMutableStateFlow.collectLatest {
weeklyAdapter.submitList(it)
}
}
}
binding.conversationView.apply {
adapter = weeklyAdapter
layoutManager = LinearLayoutManager(context).apply {
orientation = LinearLayoutManager.HORIZONTAL
stackFromEnd = true
}
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val firstVisibleItemPosition =
(recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val totalItemCount = recyclerView.adapter?.itemCount
if (totalItemCount != null) {
if (totalItemCount < previousTotalItemCount) {
previousTotalItemCount = totalItemCount
if (totalItemCount == 0) {
loading = true
}
}
}
if (totalItemCount != null) {
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false
previousTotalItemCount = totalItemCount
}
}
if (!loading && firstVisibleItemPosition < visibleThreshold) {
customManager.loadMoreData()
loading = true
}
}
})
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
fun loadMoreData(item: List<ConversationDate>) {
viewModel.startDate =
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse("2021-11-01")
viewModel.endDate =
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse("2021-11-30")
val previousData = viewModel.data
if (previousData != null) {
viewModel.data = previousData + item
}
viewModel.weeklyFormatData()
}
}
FragmentViewModel.kt
class FragmentViewModel(app: Application) : AndroidViewModel(app) {
var data: List<ConversationDate>? = null
var startDate: Date? = null
var endDate: Date? = null
private val dateRange: MutableList<Date>
get() {
val datesInRange = mutableListOf<Date>()
val tempCalendar = Calendar.getInstance()
tempCalendar.time = startDate as Date
while (tempCalendar.time <= endDate) {
datesInRange.add(tempCalendar.time)
tempCalendar.add(Calendar.DATE, 1)
}
return datesInRange
}
val prepareMutableStateFlow: MutableStateFlow<List<ConversationCount>> =
MutableStateFlow(emptyList())
fun weeklyFormatData() {
val conversationCount = mutableListOf<ConversationCount>()
viewModelScope.launch {
dateRange.forEachIndexed { index, dateRangeValue ->
val findData = data?.find {
dateRangeValue == it.dateObject
}
conversationCount.add(
ConversationCount(
setDay(dateRangeValue),
index,
findData != null
)
)
}
prepareMutableStateFlow.value = conversationCount
}
}
private fun setDay(date: Date): String? {
return SimpleDateFormat("dd", Locale.getDefault()).format(date)
}
}
My mock api response link
Problem Description
When the application is load the fragment screen will appear and showing some dates on it. I set startDate as 2021-12-01 and endDate as today date i.e. 2022-01-13
. So when starting scroll and reach to threshold of loading more data. I passed than startDate as 2021-11-01 and endDate as 2021-11-30. It added to the list but previous data is remove. I don't understand why this is happening. I am attaching my YouTube link