fill changes

This commit is contained in:
InsanusMokrassar 2021-06-17 13:39:02 +06:00
parent 63eb7b7ea8
commit e715772dbf
6 changed files with 60 additions and 4 deletions

View File

@ -2,6 +2,14 @@
## 0.5.12 ## 0.5.12
* `Common`:
* `Android`
* Extension `View#changeVisibility` has been fixed
* `Android`
* `RecyclerView`
* Default adapter got `dataCountFlow` property
* New subtype of adapter based on `StateFlow`: `StateFlowBasedRecyclerViewAdapter`
## 0.5.11 ## 0.5.11
* `Repos`: * `Repos`:

View File

@ -11,6 +11,7 @@ kotlin {
commonMain { commonMain {
dependencies { dependencies {
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
api project(":micro_utils.common")
} }
} }
androidMain { androidMain {

View File

@ -3,11 +3,19 @@ package dev.inmo.micro_utils.android.recyclerview
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.flow.*
abstract class RecyclerViewAdapter<T>: RecyclerView.Adapter<AbstractViewHolder<T>>() { abstract class RecyclerViewAdapter<T>: RecyclerView.Adapter<AbstractViewHolder<T>>() {
protected abstract val data: List<T> protected abstract val data: List<T>
private val _dataCountState by lazy {
MutableStateFlow<Int>(data.size)
}
val dataCountState: StateFlow<Int> by lazy {
_dataCountState.asStateFlow()
}
var emptyView: View? = null var emptyView: View? = null
set(value) { set(value) {
field = value field = value
@ -19,31 +27,37 @@ abstract class RecyclerViewAdapter<T>: RecyclerView.Adapter<AbstractViewHolder<T
object : RecyclerView.AdapterDataObserver() { object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) { override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
super.onItemRangeChanged(positionStart, itemCount) super.onItemRangeChanged(positionStart, itemCount)
_dataCountState.value = data.size
checkEmpty() checkEmpty()
} }
override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) { override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
super.onItemRangeChanged(positionStart, itemCount, payload) super.onItemRangeChanged(positionStart, itemCount, payload)
_dataCountState.value = data.size
checkEmpty() checkEmpty()
} }
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
_dataCountState.value = data.size
checkEmpty() checkEmpty()
} }
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
super.onItemRangeRemoved(positionStart, itemCount) super.onItemRangeRemoved(positionStart, itemCount)
_dataCountState.value = data.size
checkEmpty() checkEmpty()
} }
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
super.onItemRangeMoved(fromPosition, toPosition, itemCount) super.onItemRangeMoved(fromPosition, toPosition, itemCount)
_dataCountState.value = data.size
checkEmpty() checkEmpty()
} }
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
super.onItemRangeInserted(positionStart, itemCount) super.onItemRangeInserted(positionStart, itemCount)
_dataCountState.value = data.size
checkEmpty() checkEmpty()
} }
} }
@ -59,7 +73,7 @@ abstract class RecyclerViewAdapter<T>: RecyclerView.Adapter<AbstractViewHolder<T
private fun checkEmpty() { private fun checkEmpty() {
emptyView ?. let { emptyView ?. let {
if (data.isEmpty()) { if (dataCountState.value == 0) {
it.visibility = View.VISIBLE it.visibility = View.VISIBLE
} else { } else {
it.visibility = View.GONE it.visibility = View.GONE

View File

@ -0,0 +1,33 @@
package dev.inmo.micro_utils.android.recyclerview
import dev.inmo.micro_utils.common.Diff
import dev.inmo.micro_utils.common.PreviewFeature
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
@PreviewFeature("This feature in preview state and may contains different bugs. " +
"Besides, this feature can be changed in future in non-compatible way")
abstract class StateFlowBasedRecyclerViewAdapter<T>(
listeningScope: CoroutineScope,
dataState: StateFlow<List<T>>
) : RecyclerViewAdapter<T>() {
override var data: List<T> = emptyList()
init {
dataState.onEach {
val diff = Diff(data, it)
data = it
withContext(Dispatchers.Main) {
diff.removed.forEach {
notifyItemRemoved(it.index)
}
diff.replaced.forEach { (from, to) ->
notifyItemMoved(from.index, to.index)
}
diff.added.forEach {
notifyItemInserted(it.index)
}
}
}.launchIn(listeningScope)
}
}

View File

@ -16,7 +16,7 @@ package dev.inmo.micro_utils.common
AnnotationTarget.TYPEALIAS, AnnotationTarget.TYPEALIAS,
AnnotationTarget.TYPE_PARAMETER AnnotationTarget.TYPE_PARAMETER
) )
annotation class PreviewFeature annotation class PreviewFeature(val message: String = "It is possible, that behaviour of this thing will be changed or removed in future releases")
@RequiresOptIn( @RequiresOptIn(
"This thing is marked as warned. See message of warn to get more info", "This thing is marked as warned. See message of warn to get more info",

View File

@ -36,12 +36,12 @@ fun View.toggleVisibility(goneOnHide: Boolean = true) {
fun View.changeVisibility(show: Boolean = !isShown, goneOnHide: Boolean = true) { fun View.changeVisibility(show: Boolean = !isShown, goneOnHide: Boolean = true) {
if (show) { if (show) {
show()
} else {
if (goneOnHide) { if (goneOnHide) {
gone() gone()
} else { } else {
hide() hide()
} }
} else {
show()
} }
} }