Move adapter Job setup code to helper class (#3407)
parent
eb1ea882cf
commit
8cd1a0cb38
|
@ -19,21 +19,21 @@ import mozilla.components.browser.icons.IconRequest
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.home.sessioncontrol.Tab
|
||||
import org.mozilla.fenix.utils.AdapterWithJob
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class CollectionCreationTabListAdapter(
|
||||
val actionEmitter: Observer<CollectionCreationAction>
|
||||
) : RecyclerView.Adapter<TabViewHolder>() {
|
||||
) : AdapterWithJob<TabViewHolder>() {
|
||||
private var tabs: List<Tab> = listOf()
|
||||
private var selectedTabs: MutableSet<Tab> = mutableSetOf()
|
||||
private lateinit var job: Job
|
||||
private var hideCheckboxes = false
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TabViewHolder {
|
||||
val view =
|
||||
LayoutInflater.from(parent.context).inflate(TabViewHolder.LAYOUT_ID, parent, false)
|
||||
|
||||
return TabViewHolder(view, job)
|
||||
return TabViewHolder(view, adapterJob)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: TabViewHolder, position: Int, payloads: MutableList<Any>) {
|
||||
|
@ -73,16 +73,6 @@ class CollectionCreationTabListAdapter(
|
|||
|
||||
override fun getItemCount(): Int = tabs.size
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
job = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
fun updateData(tabs: List<Tab>, selectedTabs: Set<Tab>, hideCheckboxes: Boolean = false) {
|
||||
val diffUtil = DiffUtil.calculateDiff(
|
||||
TabDiffUtil(
|
||||
|
|
|
@ -19,13 +19,13 @@ import org.mozilla.fenix.R
|
|||
import org.mozilla.fenix.components.description
|
||||
import org.mozilla.fenix.home.sessioncontrol.Tab
|
||||
import org.mozilla.fenix.home.sessioncontrol.TabCollection
|
||||
import org.mozilla.fenix.utils.AdapterWithJob
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class SaveCollectionListAdapter(
|
||||
val actionEmitter: Observer<CollectionCreationAction>
|
||||
) : RecyclerView.Adapter<CollectionViewHolder>() {
|
||||
) : AdapterWithJob<CollectionViewHolder>() {
|
||||
|
||||
private lateinit var job: Job
|
||||
private var tabCollections = listOf<TabCollection>()
|
||||
private var selectedTabs: Set<Tab> = setOf()
|
||||
|
||||
|
@ -33,7 +33,7 @@ class SaveCollectionListAdapter(
|
|||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(CollectionViewHolder.LAYOUT_ID, parent, false)
|
||||
|
||||
return CollectionViewHolder(view, actionEmitter, job)
|
||||
return CollectionViewHolder(view, actionEmitter, adapterJob)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: CollectionViewHolder, position: Int) {
|
||||
|
@ -49,16 +49,6 @@ class SaveCollectionListAdapter(
|
|||
|
||||
override fun getItemCount(): Int = tabCollections.size
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
job = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
fun updateData(tabCollections: List<TabCollection>, selectedTabs: Set<Tab>) {
|
||||
this.tabCollections = tabCollections
|
||||
this.selectedTabs = selectedTabs
|
||||
|
|
|
@ -8,10 +8,10 @@ import android.view.LayoutInflater
|
|||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.Observer
|
||||
import kotlinx.coroutines.Job
|
||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsDeleteButtonViewHolder
|
||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsHeaderViewHolder
|
||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsListItemViewHolder
|
||||
import org.mozilla.fenix.utils.AdapterWithJob
|
||||
|
||||
private sealed class AdapterItem {
|
||||
object DeleteButton : AdapterItem()
|
||||
|
@ -34,9 +34,8 @@ private class ExceptionsList(val exceptions: List<ExceptionsItem>) {
|
|||
|
||||
class ExceptionsAdapter(
|
||||
private val actionEmitter: Observer<ExceptionsAction>
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
) : AdapterWithJob<RecyclerView.ViewHolder>() {
|
||||
private var exceptionsList: ExceptionsList = ExceptionsList(emptyList())
|
||||
private lateinit var job: Job
|
||||
|
||||
fun updateData(items: List<ExceptionsItem>) {
|
||||
this.exceptionsList = ExceptionsList(items)
|
||||
|
@ -59,7 +58,7 @@ class ExceptionsAdapter(
|
|||
return when (viewType) {
|
||||
ExceptionsDeleteButtonViewHolder.LAYOUT_ID -> ExceptionsDeleteButtonViewHolder(view, actionEmitter)
|
||||
ExceptionsHeaderViewHolder.LAYOUT_ID -> ExceptionsHeaderViewHolder(view)
|
||||
ExceptionsListItemViewHolder.LAYOUT_ID -> ExceptionsListItemViewHolder(view, actionEmitter, job)
|
||||
ExceptionsListItemViewHolder.LAYOUT_ID -> ExceptionsListItemViewHolder(view, actionEmitter, adapterJob)
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
|
@ -71,14 +70,4 @@ class ExceptionsAdapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
job = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,8 @@ import androidx.annotation.DrawableRes
|
|||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.Observer
|
||||
import kotlinx.coroutines.Job
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.NoContentMessageViewHolder
|
||||
|
@ -31,6 +29,7 @@ import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingPr
|
|||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingSectionHeaderViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingThemePickerViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingTrackingProtectionViewHolder
|
||||
import org.mozilla.fenix.utils.ListAdapterWithJob
|
||||
import mozilla.components.feature.tab.collections.Tab as ComponentTab
|
||||
|
||||
sealed class AdapterItem(@LayoutRes val viewType: Int) {
|
||||
|
@ -92,9 +91,7 @@ class AdapterItemDiffCallback : DiffUtil.ItemCallback<AdapterItem>() {
|
|||
|
||||
class SessionControlAdapter(
|
||||
private val actionEmitter: Observer<SessionControlAction>
|
||||
) : ListAdapter<AdapterItem, RecyclerView.ViewHolder>(AdapterItemDiffCallback()) {
|
||||
|
||||
private lateinit var job: Job
|
||||
) : ListAdapterWithJob<AdapterItem, RecyclerView.ViewHolder>(AdapterItemDiffCallback()) {
|
||||
|
||||
// This method triggers the ComplexMethod lint error when in fact it's quite simple.
|
||||
@SuppressWarnings("ComplexMethod")
|
||||
|
@ -102,13 +99,13 @@ class SessionControlAdapter(
|
|||
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
|
||||
return when (viewType) {
|
||||
TabHeaderViewHolder.LAYOUT_ID -> TabHeaderViewHolder(view, actionEmitter)
|
||||
TabViewHolder.LAYOUT_ID -> TabViewHolder(view, actionEmitter, job)
|
||||
TabViewHolder.LAYOUT_ID -> TabViewHolder(view, actionEmitter, adapterJob)
|
||||
SaveTabGroupViewHolder.LAYOUT_ID -> SaveTabGroupViewHolder(view, actionEmitter)
|
||||
PrivateBrowsingDescriptionViewHolder.LAYOUT_ID -> PrivateBrowsingDescriptionViewHolder(view, actionEmitter)
|
||||
NoContentMessageViewHolder.LAYOUT_ID -> NoContentMessageViewHolder(view)
|
||||
CollectionHeaderViewHolder.LAYOUT_ID -> CollectionHeaderViewHolder(view)
|
||||
CollectionViewHolder.LAYOUT_ID -> CollectionViewHolder(view, actionEmitter, job)
|
||||
TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, actionEmitter, job)
|
||||
CollectionViewHolder.LAYOUT_ID -> CollectionViewHolder(view, actionEmitter, adapterJob)
|
||||
TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, actionEmitter, adapterJob)
|
||||
OnboardingHeaderViewHolder.LAYOUT_ID -> OnboardingHeaderViewHolder(view)
|
||||
OnboardingSectionHeaderViewHolder.LAYOUT_ID -> OnboardingSectionHeaderViewHolder(view)
|
||||
OnboardingFirefoxAccountViewHolder.LAYOUT_ID -> OnboardingFirefoxAccountViewHolder(view)
|
||||
|
@ -121,16 +118,6 @@ class SessionControlAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
job = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int) = getItem(position).viewType
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
|
|
|
@ -26,10 +26,11 @@ import org.mozilla.fenix.R
|
|||
import org.mozilla.fenix.ThemeManager
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.increaseTapArea
|
||||
import org.mozilla.fenix.utils.AdapterWithJob
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class BookmarkAdapter(val emptyView: View, val actionEmitter: Observer<BookmarkAction>) :
|
||||
RecyclerView.Adapter<BookmarkAdapter.BookmarkNodeViewHolder>() {
|
||||
AdapterWithJob<BookmarkAdapter.BookmarkNodeViewHolder>() {
|
||||
|
||||
private var tree: List<BookmarkNode> = listOf()
|
||||
private var mode: BookmarkState.Mode = BookmarkState.Mode.Normal
|
||||
|
@ -37,8 +38,6 @@ class BookmarkAdapter(val emptyView: View, val actionEmitter: Observer<BookmarkA
|
|||
get() = (mode as? BookmarkState.Mode.Selecting)?.selectedItems ?: setOf()
|
||||
private var isFirstRun = true
|
||||
|
||||
lateinit var job: Job
|
||||
|
||||
fun updateData(tree: BookmarkNode?, mode: BookmarkState.Mode) {
|
||||
this.tree = tree?.children ?: listOf()
|
||||
isFirstRun = if (isFirstRun) false else {
|
||||
|
@ -54,13 +53,13 @@ class BookmarkAdapter(val emptyView: View, val actionEmitter: Observer<BookmarkA
|
|||
|
||||
return when (viewType) {
|
||||
BookmarkItemViewHolder.viewType.ordinal -> BookmarkItemViewHolder(
|
||||
view, actionEmitter, job
|
||||
view, actionEmitter, adapterJob
|
||||
)
|
||||
BookmarkFolderViewHolder.viewType.ordinal -> BookmarkFolderViewHolder(
|
||||
view, actionEmitter, job
|
||||
view, actionEmitter, adapterJob
|
||||
)
|
||||
BookmarkSeparatorViewHolder.viewType.ordinal -> BookmarkSeparatorViewHolder(
|
||||
view, actionEmitter, job
|
||||
view, actionEmitter, adapterJob
|
||||
)
|
||||
else -> throw IllegalStateException("ViewType $viewType does not match to a ViewHolder")
|
||||
}
|
||||
|
@ -75,16 +74,6 @@ class BookmarkAdapter(val emptyView: View, val actionEmitter: Observer<BookmarkA
|
|||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
job = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = tree.size
|
||||
|
||||
override fun onBindViewHolder(holder: BookmarkNodeViewHolder, position: Int) {
|
||||
|
|
|
@ -10,14 +10,13 @@ import android.view.LayoutInflater
|
|||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.Observer
|
||||
import kotlinx.coroutines.Job
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.library.history.viewholders.HistoryDeleteButtonViewHolder
|
||||
import org.mozilla.fenix.library.history.viewholders.HistoryHeaderViewHolder
|
||||
import org.mozilla.fenix.library.history.viewholders.HistoryListItemViewHolder
|
||||
import java.lang.IllegalStateException
|
||||
import java.util.Date
|
||||
import org.mozilla.fenix.utils.AdapterWithJob
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
private sealed class AdapterItem {
|
||||
object DeleteButton : AdapterItem()
|
||||
|
@ -96,10 +95,9 @@ private class HistoryList(val history: List<HistoryItem>) {
|
|||
|
||||
class HistoryAdapter(
|
||||
private val actionEmitter: Observer<HistoryAction>
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
) : AdapterWithJob<RecyclerView.ViewHolder>() {
|
||||
private var historyList: HistoryList = HistoryList(emptyList())
|
||||
private var mode: HistoryState.Mode = HistoryState.Mode.Normal
|
||||
private lateinit var job: Job
|
||||
var selected = listOf<HistoryItem>()
|
||||
|
||||
fun updateData(items: List<HistoryItem>, mode: HistoryState.Mode) {
|
||||
|
@ -126,7 +124,7 @@ class HistoryAdapter(
|
|||
return when (viewType) {
|
||||
HistoryDeleteButtonViewHolder.LAYOUT_ID -> HistoryDeleteButtonViewHolder(view, actionEmitter)
|
||||
HistoryHeaderViewHolder.LAYOUT_ID -> HistoryHeaderViewHolder(view)
|
||||
HistoryListItemViewHolder.LAYOUT_ID -> HistoryListItemViewHolder(view, actionEmitter, job)
|
||||
HistoryListItemViewHolder.LAYOUT_ID -> HistoryListItemViewHolder(view, actionEmitter, adapterJob)
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
|
@ -144,14 +142,4 @@ class HistoryAdapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
job = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ import io.reactivex.Observer
|
|||
import kotlinx.android.synthetic.main.app_share_list_item.view.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.utils.AdapterWithJob
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class AppShareRecyclerView @JvmOverloads constructor(
|
||||
|
@ -40,11 +40,10 @@ class AppShareAdapter(
|
|||
private val context: Context,
|
||||
val actionEmitter: Observer<ShareAction>,
|
||||
private val intentType: String = "text/plain"
|
||||
) : RecyclerView.Adapter<AppShareItemViewHolder>(), CoroutineScope {
|
||||
) : AdapterWithJob<AppShareItemViewHolder>(), CoroutineScope {
|
||||
|
||||
private var job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = Dispatchers.IO + job
|
||||
get() = Dispatchers.IO + adapterJob
|
||||
private var size: Int = 0
|
||||
private val shareItems: MutableList<ShareItem> = mutableListOf()
|
||||
|
||||
|
@ -87,16 +86,6 @@ class AppShareAdapter(
|
|||
override fun onBindViewHolder(holder: AppShareItemViewHolder, position: Int) {
|
||||
holder.bind(shareItems[position])
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
job = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
class AppShareItemViewHolder(
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.mozilla.fenix.utils
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* [RecyclerView.Adapter] with a [Job] for coroutines.
|
||||
* The adapterJob is setup when the adapter is attached to a RecyclerView and canceled when detached.
|
||||
*/
|
||||
abstract class AdapterWithJob<VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>() {
|
||||
protected lateinit var adapterJob: Job
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
adapterJob = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
adapterJob.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [ListAdapter] with a [Job] for coroutines.
|
||||
* The adapterJob is setup when the adapter is attached to a RecyclerView and canceled when detached.
|
||||
*/
|
||||
abstract class ListAdapterWithJob<T, VH : RecyclerView.ViewHolder>(
|
||||
diffCallback: DiffUtil.ItemCallback<T>
|
||||
) : ListAdapter<T, VH>(diffCallback) {
|
||||
protected lateinit var adapterJob: Job
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
adapterJob = Job()
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView)
|
||||
adapterJob.cancel()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue