New: Update to 1.2.0 version of RecyclerView to take advantage of new StateRestorationPolicy

which automatically handles some of the more complex state management. Without this change, the recyclerview would lose its scroll position after viewing tx details. Now it handles it perfectly due to setting transactionAdapter.stateRestorationPolicy =
            RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY
This commit is contained in:
Kevin Gorham 2020-08-28 03:19:13 -04:00
parent 94f942136b
commit 77e77ab724
No known key found for this signature in database
GPG Key ID: CCA55602DF49FC38
4 changed files with 29 additions and 15 deletions

View File

@ -119,6 +119,7 @@ dependencies {
implementation Deps.AndroidX.FRAGMENT_KTX
implementation Deps.AndroidX.LEGACY
implementation Deps.AndroidX.PAGING
implementation Deps.AndroidX.RECYCLER
implementation Deps.AndroidX.CameraX.CAMERA2
implementation Deps.AndroidX.CameraX.CORE
implementation Deps.AndroidX.CameraX.LIFECYCLE

View File

@ -6,8 +6,12 @@ import android.view.View
import androidx.lifecycle.lifecycleScope
import androidx.paging.PagedList
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import cash.z.ecc.android.R
import cash.z.ecc.android.databinding.FragmentHistoryBinding
import cash.z.ecc.android.di.viewmodel.activityViewModel
import cash.z.ecc.android.ext.goneIf
import cash.z.ecc.android.ext.onClickNavUp
import cash.z.ecc.android.ext.toColoredSpan
import cash.z.ecc.android.feedback.Report
import cash.z.ecc.android.feedback.Report.Tap.HISTORY_BACK
@ -26,6 +30,9 @@ class HistoryFragment : BaseFragment<FragmentHistoryBinding>() {
private val viewModel: HistoryViewModel by activityViewModel()
private lateinit var transactionAdapter: TransactionAdapter<ConfirmedTransaction>
private var isInitialized = false
override fun inflate(inflater: LayoutInflater): FragmentHistoryBinding =
FragmentHistoryBinding.inflate(inflater)
@ -34,6 +41,7 @@ class HistoryFragment : BaseFragment<FragmentHistoryBinding>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
twig("HistoryFragment.onViewCreated")
super.onViewCreated(view, savedInstanceState)
initTransactionUI()
binding.backButtonHitArea.onClickNavUp { tapped(HISTORY_BACK) }
lifecycleScope.launch {
binding.textAddress.text = viewModel.getAddress().toAbbreviatedAddress()
@ -43,10 +51,10 @@ class HistoryFragment : BaseFragment<FragmentHistoryBinding>() {
override fun onResume() {
twig("HistoryFragment.onResume")
super.onResume()
initTransactionUI()
viewModel.balance.collectWith(resumedScope) {
onBalanceUpdated(it)
}
viewModel.transactions.collectWith(resumedScope) { onTransactionsUpdated(it) }
}
private fun onBalanceUpdated(balance: WalletBalance) {
@ -60,29 +68,25 @@ class HistoryFragment : BaseFragment<FragmentHistoryBinding>() {
}
private fun initTransactionUI() {
adapter = TransactionAdapter()
twig("HistoryFragment.initTransactionUI")
transactionAdapter = TransactionAdapter()
transactionAdapter.stateRestorationPolicy =
RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY
binding.recyclerTransactions.apply {
layoutManager =
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
addItemDecoration(TransactionsFooter(binding.recyclerTransactions.context))
adapter = this@WalletDetailFragment.adapter
scrollToTop()
adapter = transactionAdapter
}
viewModel.transactions.collectWith(resumedScope) { onTransactionsUpdated(it) }
}
private fun onTransactionsUpdated(transactions: PagedList<ConfirmedTransaction>) {
twig("HistoryFragment.onTransactionsUpdated")
transactions.size.let { newCount ->
twig("got a new paged list of transactions of length $newCount")
binding.groupEmptyViews.goneIf(newCount > 0)
val preSize = adapter.itemCount
adapter.submitList(transactions)
// don't rescroll while the user is looking at the list, unless it's initialization
// using 4 here because there might be headers or other things that make 0 a bad pick
// 4 is about how many can fit before scrolling becomes necessary on many screens
if (preSize < 4 && newCount > preSize) {
scrollToTop()
}
val preSize = transactionAdapter.itemCount
transactionAdapter.submitList(transactions)
}
}

View File

@ -24,6 +24,10 @@ class TransactionAdapter<T : ConfirmedTransaction> :
}
) {
init {
setHasStableIds(true)
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
@ -35,4 +39,8 @@ class TransactionAdapter<T : ConfirmedTransaction> :
holder: TransactionViewHolder<T>,
position: Int
) = holder.bindTo(getItem(position))
override fun getItemId(position: Int): Long {
return getItem(position)?.id ?: -1
}
}

View File

@ -20,6 +20,7 @@ object Deps {
const val LEGACY = "androidx.legacy:legacy-support-v4:1.0.0"
const val MULTIDEX = "androidx.multidex:multidex:2.0.1"
const val PAGING = "androidx.paging:paging-runtime-ktx:2.1.2"
const val RECYCLER = "androidx.recyclerview:recyclerview:1.2.0-alpha05"
object CameraX : Version("1.0.0-beta04") {
val CAMERA2 = "androidx.camera:camera-camera2:1.0.0-beta04"
val CORE = "androidx.camera:camera-core:1.0.0-beta04"