diff --git a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapter.kt b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapter.kt index dd11704b2..271e614b5 100644 --- a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapter.kt @@ -11,20 +11,14 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import io.reactivex.Observer import kotlinx.android.synthetic.main.collection_tab_list_row.view.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import mozilla.components.browser.icons.IconRequest import org.mozilla.fenix.R import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.home.sessioncontrol.Tab -import org.mozilla.fenix.utils.AdapterWithJob -import kotlin.coroutines.CoroutineContext class CollectionCreationTabListAdapter( val actionEmitter: Observer -) : AdapterWithJob() { +) : RecyclerView.Adapter() { private var tabs: List = listOf() private var selectedTabs: MutableSet = mutableSetOf() private var hideCheckboxes = false @@ -33,7 +27,7 @@ class CollectionCreationTabListAdapter( val view = LayoutInflater.from(parent.context).inflate(TabViewHolder.LAYOUT_ID, parent, false) - return TabViewHolder(view, adapterJob) + return TabViewHolder(view) } override fun onBindViewHolder(holder: TabViewHolder, position: Int, payloads: MutableList) { @@ -44,11 +38,11 @@ class CollectionCreationTabListAdapter( is CheckChanged -> { val checkChanged = payloads[0] as CheckChanged if (checkChanged.shouldBeChecked) { - holder.view.tab_selected_checkbox.isChecked = true + holder.itemView.tab_selected_checkbox.isChecked = true } else if (checkChanged.shouldBeUnchecked) { - holder.view.tab_selected_checkbox.isChecked = false + holder.itemView.tab_selected_checkbox.isChecked = false } - holder.view.tab_selected_checkbox.visibility = + holder.itemView.tab_selected_checkbox.visibility = if (checkChanged.shouldHideCheckBox) View.GONE else View.VISIBLE } } @@ -58,7 +52,7 @@ class CollectionCreationTabListAdapter( override fun onBindViewHolder(holder: TabViewHolder, position: Int) { val tab = tabs[position] val isSelected = selectedTabs.contains(tab) - holder.view.tab_selected_checkbox.setOnCheckedChangeListener { _, isChecked -> + holder.itemView.tab_selected_checkbox.setOnCheckedChangeListener { _, isChecked -> val action = if (isChecked) { selectedTabs.add(tab) CollectionCreationAction.AddTabToSelection(tab) @@ -124,14 +118,7 @@ private class TabDiffUtil( data class CheckChanged(val shouldBeChecked: Boolean, val shouldBeUnchecked: Boolean, val shouldHideCheckBox: Boolean) -class TabViewHolder( - val view: View, - val job: Job -) : - RecyclerView.ViewHolder(view), CoroutineScope { - - override val coroutineContext: CoroutineContext - get() = Dispatchers.IO + job +class TabViewHolder(view: View) : RecyclerView.ViewHolder(view) { private var tab: Tab? = null private val checkbox = view.tab_selected_checkbox!! @@ -144,21 +131,15 @@ class TabViewHolder( fun bind(tab: Tab, isSelected: Boolean, shouldHideCheckBox: Boolean) { this.tab = tab - view.hostname.text = tab.hostname - view.tab_title.text = tab.title + itemView.hostname.text = tab.hostname + itemView.tab_title.text = tab.title checkbox.visibility = if (shouldHideCheckBox) View.INVISIBLE else View.VISIBLE - view.isClickable = !shouldHideCheckBox + itemView.isClickable = !shouldHideCheckBox if (checkbox.isChecked != isSelected) { checkbox.isChecked = isSelected } - launch(Dispatchers.IO) { - val bitmap = view.favicon_image.context.components.core.icons - .loadIcon(IconRequest(tab.url)).await().bitmap - launch(Dispatchers.Main) { - view.favicon_image.setImageBitmap(bitmap) - } - } + itemView.context.components.core.icons.loadIntoView(itemView.favicon_image, tab.url) } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationUIView.kt b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationUIView.kt index fee2b97fd..b6e7424f2 100644 --- a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationUIView.kt +++ b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationUIView.kt @@ -23,9 +23,6 @@ import io.reactivex.Observer import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.component_collection_creation.* import kotlinx.android.synthetic.main.component_collection_creation.view.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import mozilla.components.support.ktx.android.view.hideKeyboard import mozilla.components.support.ktx.android.view.showKeyboard import org.mozilla.fenix.R @@ -36,7 +33,6 @@ import org.mozilla.fenix.ext.urlToTrimmedHost import org.mozilla.fenix.home.sessioncontrol.Tab import org.mozilla.fenix.home.sessioncontrol.TabCollection import org.mozilla.fenix.mvi.UIView -import kotlin.coroutines.CoroutineContext class CollectionCreationUIView( container: ViewGroup, @@ -46,10 +42,7 @@ class CollectionCreationUIView( container, actionEmitter, changesObservable -), CoroutineScope { - private lateinit var job: Job - override val coroutineContext: CoroutineContext - get() = Dispatchers.Main + job +) { override val view = LayoutInflater.from(container.context) .inflate(R.layout.component_collection_creation, container, true) @@ -67,7 +60,6 @@ class CollectionCreationUIView( private val transition = AutoTransition() init { - job = Job() transition.duration = TRANSITION_DURATION selectTabsConstraints.clone(collection_constraint_layout) diff --git a/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsAdapter.kt b/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsAdapter.kt index 3b3a0ffb5..ea4d41788 100644 --- a/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsAdapter.kt @@ -10,7 +10,6 @@ import androidx.recyclerview.widget.RecyclerView 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,7 +33,7 @@ private class ExceptionsList(val exceptions: List) { class ExceptionsAdapter( private val interactor: ExceptionsInteractor -) : AdapterWithJob() { +) : RecyclerView.Adapter() { private var exceptionsList: ExceptionsList = ExceptionsList(emptyList()) fun updateData(items: List) { @@ -61,11 +60,7 @@ class ExceptionsAdapter( interactor ) ExceptionsHeaderViewHolder.LAYOUT_ID -> ExceptionsHeaderViewHolder(view) - ExceptionsListItemViewHolder.LAYOUT_ID -> ExceptionsListItemViewHolder( - view, - interactor, - adapterJob - ) + ExceptionsListItemViewHolder.LAYOUT_ID -> ExceptionsListItemViewHolder(view, interactor) else -> throw IllegalStateException() } } diff --git a/app/src/main/java/org/mozilla/fenix/exceptions/viewholders/ExceptionsListItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/exceptions/viewholders/ExceptionsListItemViewHolder.kt index 60bdf564b..dd27299dd 100644 --- a/app/src/main/java/org/mozilla/fenix/exceptions/viewholders/ExceptionsListItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/exceptions/viewholders/ExceptionsListItemViewHolder.kt @@ -7,25 +7,16 @@ package org.mozilla.fenix.exceptions.viewholders import android.view.View import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.exception_item.view.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import mozilla.components.browser.icons.IconRequest import org.mozilla.fenix.R import org.mozilla.fenix.exceptions.ExceptionsInteractor import org.mozilla.fenix.exceptions.ExceptionsItem import org.mozilla.fenix.ext.components -import kotlin.coroutines.CoroutineContext +import org.mozilla.fenix.ext.loadIntoView class ExceptionsListItemViewHolder( view: View, - private val interactor: ExceptionsInteractor, - val job: Job -) : RecyclerView.ViewHolder(view), CoroutineScope { - - override val coroutineContext: CoroutineContext - get() = Dispatchers.IO + job + private val interactor: ExceptionsInteractor +) : RecyclerView.ViewHolder(view) { private val favicon = view.favicon_image private val url = view.domainView @@ -48,13 +39,7 @@ class ExceptionsListItemViewHolder( } private fun updateFavIcon(url: String) { - launch(Dispatchers.IO) { - val bitmap = favicon.context.components.core.icons - .loadIcon(IconRequest(url)).await().bitmap - launch(Dispatchers.Main) { - favicon.setImageBitmap(bitmap) - } - } + favicon.context.components.core.icons.loadIntoView(favicon, url) } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/ext/BrowserIcons.kt b/app/src/main/java/org/mozilla/fenix/ext/BrowserIcons.kt new file mode 100644 index 000000000..899da6ea6 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/ext/BrowserIcons.kt @@ -0,0 +1,11 @@ +/* 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/. */ + +package org.mozilla.fenix.ext + +import android.widget.ImageView +import mozilla.components.browser.icons.BrowserIcons +import mozilla.components.browser.icons.IconRequest + +fun BrowserIcons.loadIntoView(view: ImageView, url: String) = loadIntoView(view, IconRequest(url)) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt index 3af79fa2d..e220276ac 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt @@ -11,6 +11,7 @@ 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 org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHolder @@ -29,7 +30,6 @@ 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) { @@ -91,7 +91,7 @@ class AdapterItemDiffCallback : DiffUtil.ItemCallback() { class SessionControlAdapter( private val actionEmitter: Observer -) : ListAdapterWithJob(AdapterItemDiffCallback()) { +) : ListAdapter(AdapterItemDiffCallback()) { // This method triggers the ComplexMethod lint error when in fact it's quite simple. @SuppressWarnings("ComplexMethod") @@ -99,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, adapterJob) + TabViewHolder.LAYOUT_ID -> TabViewHolder(view, actionEmitter) 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) - TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, actionEmitter, adapterJob) + TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, actionEmitter) OnboardingHeaderViewHolder.LAYOUT_ID -> OnboardingHeaderViewHolder(view) OnboardingSectionHeaderViewHolder.LAYOUT_ID -> OnboardingSectionHeaderViewHolder(view) OnboardingFirefoxAccountViewHolder.LAYOUT_ID -> OnboardingFirefoxAccountViewHolder(view) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt index c3e1d694a..758de0a31 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt @@ -12,34 +12,25 @@ import androidx.recyclerview.widget.RecyclerView import io.reactivex.Observer import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.tab_in_collection.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import mozilla.components.browser.icons.IconRequest import mozilla.components.support.ktx.android.util.dpToFloat import org.jetbrains.anko.backgroundColor import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getColorFromAttr import org.mozilla.fenix.ext.increaseTapArea +import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.ext.urlToTrimmedHost import org.mozilla.fenix.home.sessioncontrol.CollectionAction import org.mozilla.fenix.home.sessioncontrol.SessionControlAction import org.mozilla.fenix.home.sessioncontrol.TabCollection import org.mozilla.fenix.home.sessioncontrol.onNext -import kotlin.coroutines.CoroutineContext import mozilla.components.feature.tab.collections.Tab as ComponentTab class TabInCollectionViewHolder( val view: View, val actionEmitter: Observer, - val job: Job, override val containerView: View? = view -) : RecyclerView.ViewHolder(view), LayoutContainer, CoroutineScope { - - override val coroutineContext: CoroutineContext - get() = Dispatchers.IO + job +) : RecyclerView.ViewHolder(view), LayoutContainer { lateinit var collection: TabCollection private set @@ -82,13 +73,7 @@ class TabInCollectionViewHolder( collection_tab_hostname.text = tab.url.urlToTrimmedHost(view.context) collection_tab_title.text = tab.title - launch(Dispatchers.IO) { - val bitmap = collection_tab_icon.context.components.core.icons - .loadIcon(IconRequest(tab.url)).await().bitmap - launch(Dispatchers.Main) { - collection_tab_icon.setImageBitmap(bitmap) - } - } + collection_tab_icon.context.components.core.icons.loadIntoView(collection_tab_icon, tab.url) // If I'm the last one... if (isLastTab) { diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt index d6b37ad38..78a74c3dd 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt @@ -12,33 +12,24 @@ import androidx.recyclerview.widget.RecyclerView import io.reactivex.Observer import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.tab_list_row.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import mozilla.components.browser.icons.IconRequest import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.support.ktx.android.util.dpToFloat import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.increaseTapArea +import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.home.sessioncontrol.SessionControlAction import org.mozilla.fenix.home.sessioncontrol.Tab import org.mozilla.fenix.home.sessioncontrol.TabAction import org.mozilla.fenix.home.sessioncontrol.onNext -import kotlin.coroutines.CoroutineContext class TabViewHolder( view: View, actionEmitter: Observer, - private val job: Job, override val containerView: View? = view ) : - RecyclerView.ViewHolder(view), LayoutContainer, CoroutineScope { - - override val coroutineContext: CoroutineContext - get() = Dispatchers.IO + job + RecyclerView.ViewHolder(view), LayoutContainer { var tab: Tab? = null private var tabMenu: TabItemMenu @@ -92,13 +83,7 @@ class TabViewHolder( private fun updateTabUI(tab: Tab) { hostname.text = tab.hostname tab_title.text = tab.title - launch(Dispatchers.IO) { - val bitmap = favicon_image.context.components.core.icons - .loadIcon(IconRequest(tab.url)).await().bitmap - launch(Dispatchers.Main) { - favicon_image.setImageBitmap(bitmap) - } - } + favicon_image.context.components.core.icons.loadIntoView(favicon_image, tab.url) } fun updateSelected(selected: Boolean) { diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt index 054d7f612..2c90aeddf 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt @@ -13,12 +13,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.bookmark_row.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch import mozilla.appservices.places.BookmarkRoot -import mozilla.components.browser.icons.IconRequest import mozilla.components.browser.menu.BrowserMenu import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNodeType @@ -26,11 +21,10 @@ 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 +import org.mozilla.fenix.ext.loadIntoView class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteractor) : - AdapterWithJob() { + RecyclerView.Adapter() { private var tree: List = listOf() private var mode: BookmarkState.Mode = BookmarkState.Mode.Normal @@ -86,13 +80,13 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto return when (viewType) { BookmarkItemViewHolder.viewType.ordinal -> BookmarkItemViewHolder( - view, interactor, adapterJob + view, interactor ) BookmarkFolderViewHolder.viewType.ordinal -> BookmarkFolderViewHolder( - view, interactor, adapterJob + view, interactor ) BookmarkSeparatorViewHolder.viewType.ordinal -> BookmarkSeparatorViewHolder( - view, interactor, adapterJob + view, interactor ) else -> throw IllegalStateException("ViewType $viewType does not match to a ViewHolder") } @@ -120,13 +114,8 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto open class BookmarkNodeViewHolder( view: View, val interactor: BookmarkViewInteractor, - private val job: Job, override val containerView: View? = view - ) : - RecyclerView.ViewHolder(view), LayoutContainer, CoroutineScope { - - override val coroutineContext: CoroutineContext - get() = Dispatchers.Main + job + ) : RecyclerView.ViewHolder(view), LayoutContainer { open fun bind(item: BookmarkNode, mode: BookmarkState.Mode, selected: Boolean) {} } @@ -134,10 +123,9 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto class BookmarkItemViewHolder( view: View, interactor: BookmarkViewInteractor, - job: Job, override val containerView: View? = view ) : - BookmarkNodeViewHolder(view, interactor, job, containerView) { + BookmarkNodeViewHolder(view, interactor, containerView) { @Suppress("ComplexMethod") override fun bind(item: BookmarkNode, mode: BookmarkState.Mode, selected: Boolean) { @@ -209,14 +197,9 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto bookmark_favicon.backgroundTintList = backgroundTintList if (selected) bookmark_favicon.setImageResource(R.drawable.mozac_ic_check) - if (!selected && item.url?.startsWith("http") == true) { - launch(Dispatchers.IO) { - val bitmap = bookmark_layout.context.components.core.icons - .loadIcon(IconRequest(item.url!!)).await().bitmap - launch(Dispatchers.Main) { - bookmark_favicon.setImageBitmap(bitmap) - } - } + val url = item.url ?: return + if (!selected && url.startsWith("http")) { + bookmark_layout.context.components.core.icons.loadIntoView(bookmark_favicon, url) } } @@ -251,10 +234,9 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto class BookmarkFolderViewHolder( view: View, interactor: BookmarkViewInteractor, - job: Job, override val containerView: View? = view ) : - BookmarkNodeViewHolder(view, interactor, job, containerView) { + BookmarkNodeViewHolder(view, interactor, containerView) { override fun bind(item: BookmarkNode, mode: BookmarkState.Mode, selected: Boolean) { containerView?.context?.let { @@ -353,9 +335,8 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto class BookmarkSeparatorViewHolder( view: View, interactor: BookmarkViewInteractor, - job: Job, override val containerView: View? = view - ) : BookmarkNodeViewHolder(view, interactor, job, containerView) { + ) : BookmarkNodeViewHolder(view, interactor, containerView) { override fun bind(item: BookmarkNode, mode: BookmarkState.Mode, selected: Boolean) { diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryAdapter.kt index 5911c3224..fe83c229f 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryAdapter.kt @@ -14,7 +14,6 @@ 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 org.mozilla.fenix.utils.AdapterWithJob import java.util.Calendar import java.util.Date @@ -94,7 +93,7 @@ private class HistoryList(val history: List) { } class HistoryAdapter(private val historyInteractor: HistoryInteractor) : - AdapterWithJob() { + RecyclerView.Adapter() { private var historyList: HistoryList = HistoryList(emptyList()) private var mode: HistoryState.Mode = HistoryState.Mode.Normal var selected = listOf() @@ -158,16 +157,9 @@ class HistoryAdapter(private val historyInteractor: HistoryInteractor) : val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false) return when (viewType) { - HistoryDeleteButtonViewHolder.LAYOUT_ID -> HistoryDeleteButtonViewHolder( - view, - historyInteractor - ) + HistoryDeleteButtonViewHolder.LAYOUT_ID -> HistoryDeleteButtonViewHolder(view, historyInteractor) HistoryHeaderViewHolder.LAYOUT_ID -> HistoryHeaderViewHolder(view) - HistoryListItemViewHolder.LAYOUT_ID -> HistoryListItemViewHolder( - view, - historyInteractor, - adapterJob - ) + HistoryListItemViewHolder.LAYOUT_ID -> HistoryListItemViewHolder(view, historyInteractor) else -> throw IllegalStateException() } } diff --git a/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt index 443af9df5..0cf675d6f 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt @@ -9,29 +9,20 @@ import android.widget.CompoundButton import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.history_list_item.view.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import mozilla.components.browser.icons.IconRequest import mozilla.components.browser.menu.BrowserMenu import org.mozilla.fenix.R import org.mozilla.fenix.ThemeManager import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.library.history.HistoryInteractor import org.mozilla.fenix.library.history.HistoryItem import org.mozilla.fenix.library.history.HistoryItemMenu import org.mozilla.fenix.library.history.HistoryState -import kotlin.coroutines.CoroutineContext class HistoryListItemViewHolder( view: View, - private val historyInteractor: HistoryInteractor, - val job: Job -) : RecyclerView.ViewHolder(view), CoroutineScope { - - override val coroutineContext: CoroutineContext - get() = Dispatchers.IO + job + private val historyInteractor: HistoryInteractor +) : RecyclerView.ViewHolder(view) { private val favicon = view.history_favicon private val title = view.history_title @@ -124,13 +115,7 @@ class HistoryListItemViewHolder( } private fun updateFavIcon(url: String) { - launch(Dispatchers.IO) { - val bitmap = favicon.context.components.core.icons - .loadIcon(IconRequest(url)).await().bitmap - launch(Dispatchers.Main) { - favicon.setImageBitmap(bitmap) - } - } + favicon.context.components.core.icons.loadIntoView(favicon, url) } private fun setClickListeners( diff --git a/app/src/main/java/org/mozilla/fenix/settings/SearchEngineListPreference.kt b/app/src/main/java/org/mozilla/fenix/settings/SearchEngineListPreference.kt index e0bad163d..3007653ce 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SearchEngineListPreference.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SearchEngineListPreference.kt @@ -17,23 +17,17 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.preference.Preference import androidx.preference.PreferenceViewHolder import kotlinx.android.synthetic.main.search_engine_radio_button.view.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import mozilla.components.browser.search.SearchEngine import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.utils.Settings -import kotlin.coroutines.CoroutineContext abstract class SearchEngineListPreference @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.preferenceStyle -) : Preference(context, attrs, defStyleAttr), CompoundButton.OnCheckedChangeListener, CoroutineScope { - private val job = Job() - override val coroutineContext: CoroutineContext - get() = job + Dispatchers.Main +) : Preference(context, attrs, defStyleAttr), CompoundButton.OnCheckedChangeListener { + protected var searchEngines: List = emptyList() protected var searchEngineGroup: RadioGroup? = null @@ -54,11 +48,6 @@ abstract class SearchEngineListPreference @JvmOverloads constructor( refreshSearchEngineViews(context) } - override fun onDetached() { - job.cancel() - super.onDetached() - } - protected abstract fun onSearchEngineSelected(searchEngine: SearchEngine) protected abstract fun updateDefaultItem(defaultButton: CompoundButton) diff --git a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt index 2a64d6f6c..0a54e8905 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt @@ -4,7 +4,6 @@ package org.mozilla.fenix.settings -import android.graphics.drawable.BitmapDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -24,20 +23,17 @@ import androidx.paging.PagedListAdapter import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main -import kotlinx.coroutines.Job import kotlinx.coroutines.launch -import mozilla.components.browser.icons.IconRequest import mozilla.components.feature.sitepermissions.SitePermissions import org.jetbrains.anko.alert import org.jetbrains.anko.noButton import org.jetbrains.anko.yesButton import org.mozilla.fenix.R import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.ext.nav -import kotlin.coroutines.CoroutineContext private const val MAX_ITEMS_PER_PAGE = 50 @@ -135,21 +131,7 @@ class SitePermissionsViewHolder(val view: View, val iconView: ImageView, val sit RecyclerView.ViewHolder(view) class ExceptionsAdapter(private val clickListener: View.OnClickListener) : - PagedListAdapter(diffCallback), CoroutineScope { - private lateinit var job: Job - - override val coroutineContext: CoroutineContext - get() = Main + job - - override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { - super.onAttachedToRecyclerView(recyclerView) - job = Job() - } - - override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { - super.onDetachedFromRecyclerView(recyclerView) - job.cancel() - } + PagedListAdapter(diffCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SitePermissionsViewHolder { val context = parent.context @@ -164,15 +146,7 @@ class ExceptionsAdapter(private val clickListener: View.OnClickListener) : val sitePermissions = requireNotNull(getItem(position)) val context = holder.view.context - launch(IO) { - - val bitmap = context.components.core.icons - .loadIcon(IconRequest("https://${sitePermissions.origin}/")).await().bitmap - launch(Main) { - val drawable = BitmapDrawable(context.resources, bitmap) - holder.iconView.setImageDrawable(drawable) - } - } + context.components.core.icons.loadIntoView(holder.iconView, "https://${sitePermissions.origin}/") holder.siteTextView.text = sitePermissions.origin holder.view.tag = sitePermissions holder.view.setOnClickListener(clickListener) diff --git a/app/src/main/java/org/mozilla/fenix/share/AppShareView.kt b/app/src/main/java/org/mozilla/fenix/share/AppShareView.kt index bf4be1a69..53529fa0d 100644 --- a/app/src/main/java/org/mozilla/fenix/share/AppShareView.kt +++ b/app/src/main/java/org/mozilla/fenix/share/AppShareView.kt @@ -19,11 +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.cancel 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( context: Context, @@ -40,10 +39,10 @@ class AppShareAdapter( private val context: Context, val actionEmitter: Observer, private val intentType: String = "text/plain" -) : AdapterWithJob(), CoroutineScope { +) : RecyclerView.Adapter() { + + private var scope = CoroutineScope(Dispatchers.IO) - override val coroutineContext: CoroutineContext - get() = Dispatchers.IO + adapterJob private var size: Int = 0 private val shareItems: MutableList = mutableListOf() @@ -53,7 +52,7 @@ class AppShareAdapter( flags = FLAG_ACTIVITY_NEW_TASK } - launch { + scope.launch { val activities = context.packageManager.queryIntentActivities(testIntent, 0) val items = activities.map { resolveInfo -> @@ -86,6 +85,11 @@ class AppShareAdapter( override fun onBindViewHolder(holder: AppShareItemViewHolder, position: Int) { holder.bind(shareItems[position]) } + + override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { + super.onDetachedFromRecyclerView(recyclerView) + scope.cancel() + } } class AppShareItemViewHolder( diff --git a/app/src/main/java/org/mozilla/fenix/utils/AdapterWithJob.kt b/app/src/main/java/org/mozilla/fenix/utils/AdapterWithJob.kt deleted file mode 100644 index 98b8f4cb3..000000000 --- a/app/src/main/java/org/mozilla/fenix/utils/AdapterWithJob.kt +++ /dev/null @@ -1,38 +0,0 @@ -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 initialized to a RecyclerView and canceled when detached. - */ -abstract class AdapterWithJob : RecyclerView.Adapter() { - protected var adapterJob: Job = 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 initialized to a RecyclerView and canceled when detached. - */ -abstract class ListAdapterWithJob( - diffCallback: DiffUtil.ItemCallback -) : ListAdapter(diffCallback) { - protected var adapterJob: Job = Job() - - override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { - super.onDetachedFromRecyclerView(recyclerView) - adapterJob.cancel() - } -} diff --git a/app/src/main/res/values/tags.xml b/app/src/main/res/values/tags.xml new file mode 100644 index 000000000..fc8223cf4 --- /dev/null +++ b/app/src/main/res/values/tags.xml @@ -0,0 +1,7 @@ + + + + +