Address coroutine scope leaks in custom views

This commit is contained in:
arkon 2021-01-07 19:16:26 -05:00
parent b18a794eca
commit 8e613d03e3
5 changed files with 33 additions and 21 deletions

View file

@ -10,15 +10,10 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.widget.textChanges
import eu.kanade.tachiyomi.widget.SimpleTextWatcher
open class TextItem(val filter: Filter.Text) : AbstractFlexibleItem<TextItem.Holder>() {
private val scope = MainScope()
override fun getLayoutRes(): Int {
return R.layout.navigation_view_text
}
@ -30,9 +25,11 @@ open class TextItem(val filter: Filter.Text) : AbstractFlexibleItem<TextItem.Hol
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, holder: Holder, position: Int, payloads: List<Any?>?) {
holder.wrapper.hint = filter.name
holder.edit.setText(filter.state)
holder.edit.textChanges()
.onEach { filter.state = it.toString() }
.launchIn(scope)
holder.edit.addTextChangedListener(object : SimpleTextWatcher() {
override fun onTextChanged(text: CharSequence, start: Int, before: Int, count: Int) {
filter.state = text.toString()
}
})
}
override fun equals(other: Any?): Boolean {

View file

@ -97,7 +97,7 @@ class LibraryAdapter(private val controller: LibraryController) : RecyclerViewPa
fun onDestroy() {
for (view in boundViews) {
if (view is LibraryCategoryView) {
view.unsubscribe()
view.onDestroy()
}
}
}

View file

@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.inflate
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.recyclerview.scrollStateChanges
@ -155,7 +156,12 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
unsubscribe()
}
fun unsubscribe() {
fun onDestroy() {
unsubscribe()
scope.cancel()
}
private fun unsubscribe() {
subscriptions.clear()
}

View file

@ -7,10 +7,6 @@ import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import eu.kanade.tachiyomi.databinding.DownloadCustomAmountBinding
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.widget.textChanges
import timber.log.Timber
/**
@ -35,8 +31,6 @@ class DialogCustomDownloadView @JvmOverloads constructor(context: Context, attrs
*/
private var max = 0
private val scope = MainScope()
private val binding: DownloadCustomAmountBinding
init {
@ -71,16 +65,16 @@ class DialogCustomDownloadView @JvmOverloads constructor(context: Context, attrs
}
// When user inputs custom number set amount equal to input.
binding.myNumber.textChanges()
.onEach {
binding.myNumber.addTextChangedListener(object : SimpleTextWatcher() {
override fun onTextChanged(text: CharSequence, start: Int, before: Int, count: Int) {
try {
amount = getAmount(Integer.parseInt(it.toString()))
amount = getAmount(text.toString().toInt())
} catch (error: NumberFormatException) {
// Catch NumberFormatException to prevent parse exception when input is empty.
Timber.e(error)
}
}
.launchIn(scope)
})
}
/**

View file

@ -0,0 +1,15 @@
package eu.kanade.tachiyomi.widget
import android.text.Editable
import android.text.TextWatcher
open class SimpleTextWatcher : TextWatcher {
override fun beforeTextChanged(text: CharSequence, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(text: CharSequence, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(text: Editable) {
}
}