From 77e77ab724c5fe1c6de70eefe0ca6ec330aa746d Mon Sep 17 00:00:00 2001 From: Kevin Gorham Date: Fri, 28 Aug 2020 03:19:13 -0400 Subject: [PATCH] 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 --- app/build.gradle | 1 + .../ecc/android/ui/history/HistoryFragment.kt | 34 +++++++++++-------- .../android/ui/history/TransactionAdapter.kt | 8 +++++ .../java/cash/z/ecc/android/Dependencies.kt | 1 + 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index db5aed7..1862f4b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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 diff --git a/app/src/main/java/cash/z/ecc/android/ui/history/HistoryFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/history/HistoryFragment.kt index bccd409..62c22b3 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/history/HistoryFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/history/HistoryFragment.kt @@ -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() { private val viewModel: HistoryViewModel by activityViewModel() + private lateinit var transactionAdapter: TransactionAdapter + + private var isInitialized = false override fun inflate(inflater: LayoutInflater): FragmentHistoryBinding = FragmentHistoryBinding.inflate(inflater) @@ -34,6 +41,7 @@ class HistoryFragment : BaseFragment() { 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() { 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() { } 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) { 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) } } diff --git a/app/src/main/java/cash/z/ecc/android/ui/history/TransactionAdapter.kt b/app/src/main/java/cash/z/ecc/android/ui/history/TransactionAdapter.kt index 35aa2ec..4b413a5 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/history/TransactionAdapter.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/history/TransactionAdapter.kt @@ -24,6 +24,10 @@ class TransactionAdapter : } ) { + init { + setHasStableIds(true) + } + override fun onCreateViewHolder( parent: ViewGroup, viewType: Int @@ -35,4 +39,8 @@ class TransactionAdapter : holder: TransactionViewHolder, position: Int ) = holder.bindTo(getItem(position)) + + override fun getItemId(position: Int): Long { + return getItem(position)?.id ?: -1 + } } diff --git a/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt b/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt index ecc46a0..ff9333f 100644 --- a/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt +++ b/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt @@ -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"