I am using Firebase firestore pagination and ViewModel class in my project, I have setup an onScroll listener for recyclerview, and fetching data on scroll but when i Navigate to another fragment and back to the main fragment, the whole items are duplicated, How can i fix this issue??
Here is my code
NewsViewModel.kt
class NewsViewModel : ViewModel() {
private val repo = FirebaseRepo(this)
val mutableLiveData = MutableLiveData<List<News>>()
fun getNewsList(tm:Timestamp): LiveData<List<News>> {
repo.getNewsData(tm)
return mutableLiveData
}
}
Repository.kt
class FirebaseRepo(private val viewModel: NewsViewModel) {
private val db = FirebaseFirestore.getInstance().collection("news")
fun getNewsData(tm: Timestamp) {
val newsList = ArrayList<News>()
if(viewModel.mutableLiveData.value != null) {
newsList.addAll(viewModel.mutableLiveData.value!!)
}
db
.orderBy("timestamp", Query.Direction.DESCENDING)
.whereLessThan("timestamp",tm)
.limit(6)
.get()
.addOnSuccessListener {
Log.i("CodeCamp", it.toString())
for (doc in it) {
val imgUrl = doc.getString("imageUrl")
val heading = doc.getString("headline")
val timestamp = doc.getTimestamp("timestamp")
val tagline = doc.getString("tagline")
val type = doc.getString("type")
newsList.add(News(doc.id, imgUrl!!, heading!!, tagline!!, type!!, timestamp!!))
}
viewModel.mutableLiveData.value = newsList
}
}
}
MainActivity.kt
viewModel = ViewModelProvider(this).get(NewsViewModel::class.java)
val layoutManager = LinearLayoutManager(view.context)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = newsAdapter
recyclerView.addItemDecoration(DividerItemDecoration(view.context, RecyclerView.VERTICAL))
//observe to the viewModel
viewModel.getNewsList(Timestamp.now()).observe(viewLifecycleOwner, Observer {
newsAdapter.submitList(it)
})
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val visibleItemCount = layoutManager.childCount
val totalItemCount = layoutManager.itemCount
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0
&& totalItemCount >= PAGE_SIZE && !isLoading
) {
isLoading != isLoading
val list = viewModel.mutableLiveData.value!!
viewModel.getNewsList(list[list.size - 1].timestamp).value
Handler().postDelayed({
isLoading != isLoading
},2000)
}
}
})
My Adapter
class NewsAdapter : ListAdapter<News, NewsAdapter.ViewHolder> (NEWS_COMPARATOR) {
companion object {
private val NEWS_COMPARATOR = object : DiffUtil.ItemCallback<News>() {
override fun areItemsTheSame(old: News, new: News): Boolean = old.id == new.id
override fun areContentsTheSame(old: News, new: News): Boolean = old == new
}
}
class ViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
fun bindView(news: News) {
Glide.with(view).load(news.imageUrl).into(itemView.img)
itemView.news_title.text = news.heading
itemView.news_src.text = news.tagline
itemView.news_type.text = news.type
itemView.news_time.text = DateTime.getTimeAgo(news.timestamp.seconds)
itemView.setOnClickListener {
it.findNavController().navigate(R.id.action_homeFragment_to_newsFragment, bundleOf("id" to news.id))
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_news,parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val news = getItem(position)
holder.bindView(news)
}
}