'How to load the recycler view adapter on resume event
I have a fragment which displays a list in recyler view (chargeHistoryList). all the code is written in onActivityCreated, so this gets called only once when the fragment is called. onResume method is pretty blank at the moment.
Issue I am having is, when I initially open this fragment ChargeHistoryFragment recyclerview is loaded correctly with data. when I put the app in the background and comeback to it the recyclerview is empty, no data is shown.
I tried adding the code in onViewCreated but that also gets called only once and onresume is the only lifecylce method thats gets called when the app goes in background and comes back to foreground.
How can I make the adapter load with data when only onResume is called
ChargeHistoryFragment
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.charge_history_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
baseActivity?.updateAppBar(title = screenTitle)
chargeHistoryList.setHasFixedSize(true)
chargeHistoryList.addItemDecoration(VerticalSpaceItemDecoration(8))
onChargeSelectListener = activity as OnChargeSelectListener
var chargeHistoryAdapter = ChargeHistoryDataAdapter(dateFormatter,
decimalFormatter,
timeFormatter,
onItemClickListener = this,
currencies = listOf())
chargeHistoryList.adapter = chargeHistoryAdapter
viewModel.getCurrencies().observe(owner = this) { resource ->
when (resource.status) {
SUCCESS -> {
resource.data?.let {
chargeHistoryAdapter = ChargeHistoryDataAdapter(dateFormatter,
decimalFormatter,
timeFormatter,
onItemClickListener = this,
currencies = it)
chargeHistoryList.adapter = chargeHistoryAdapter
}
}
LOADING, ERROR -> { /** DO NOTHING **/ }
}
}
lifecycleScope.launch {
viewModel.chargeHistory.collectLatest {
chargeHistoryAdapter.submitData(it)
}
}
chargeHistoryAdapter.addLoadStateListener { loadState ->
if (loadState.source.refresh is LoadState.NotLoading && loadState.append.endOfPaginationReached && chargeHistoryAdapter.itemCount < 1) {
setEmptyViewVisibility(true)
} else {
setEmptyViewVisibility(false)
}
}
}
override fun onResume() {
super.onResume()
}
Adapter
class ChargeHistoryDataAdapter(
private val dateFormatter: DateFormatter,
private val decimalFormatter: DecimalFormat,
private val timeFormatter: TimeFormatter,
private val currencies: List<CurrencyDB>,
private val onItemClickListener: ListAdapterBase.OnItemClickListener<ChargingSessionDB?>
) : PagingDataAdapter<ChargingSessionDB, ChargeSessionViewHolder>(ChargingSessionDiffUtilCallback()){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChargeSessionViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.charge_history_list_item, parent, false)
return ChargeSessionViewHolder(view, dateFormatter, decimalFormatter, timeFormatter, currencies)
}
override fun onBindViewHolder(holder: ChargeSessionViewHolder, position: Int) {
holder.bindTo(getItem(position), position, onItemClickListener)
}
}
Thanks in advance R
Edit after @Tenfour04 suggestion
onActivityCreated
viewModel.getCurrencies().observe(owner = viewLifecycleOwner) { resource ->
when (resource.status) {
SUCCESS -> {
Log.d("issueHappening", "viewModel.getCurrencies()")
resource.data?.let {
chargeHistoryAdapter = ChargeHistoryDataAdapter(dateFormatter,
decimalFormatter,
timeFormatter,
onItemClickListener = this,
currencies = it)
chargeHistoryList.adapter = chargeHistoryAdapter
}
}
LOADING, ERROR -> { /** DO NOTHING **/ }
}
}
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.chargeHistory.collectLatest {
Log.d("issueHappening", "viewModel.chargeHistory")
chargeHistoryAdapter.submitData(it)
}
}
}
Solution 1:[1]
You aren't collecting on the right lifecycle. This:
lifecycleScope.launch {
viewModel.chargeHistory.collectLatest {
chargeHistoryAdapter.submitData(it)
}
}
Should be:
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.chargeHistory.collect {
chargeHistoryAdapter.submitData(it)
}
}
}
or:
viewModel.chargeHistory
.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED)
.onEach { chargeHistoryAdapter.submitData(it) }
.launchIn(viewLifecycleOwner.lifecycleScope)
I changed collectLatest() to collect() because passing a list to the adapter is a trivial action that will return instantly and has no possible way of being cancelled or needing to be cancelled (I'm assuming it is a non-blocking, non-suspending function). If your collecting takes a long time and is cooperative with cancellation, then it would make sense to use collectLatest. There is no onEachLatest, but you could possibly use transformLatest in place of onEach if you needed it.
Likewise with your LiveData observer, you should observe with the viewLifeCycleOwner, not the Fragment itself.
viewModel.getCurrencies().observe(owner = viewLifecycleOwner) { resource ->
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tenfour04 |
