1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

Data view | Performance optimizations (#1474)

This commit is contained in:
Evgenii Kozlov 2021-05-18 13:20:32 +03:00 committed by GitHub
parent e1ab8489a7
commit 8c9d1a0d42
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 104 additions and 68 deletions

View file

@ -1,7 +1,7 @@
on:
pull_request:
# add "synchronize" in "types", in order to trigger workflow for pull request commit(s) pushes.
types: [open]
types: [opened]
branches: [develop]
name: Run debug unit tests
jobs:

View file

@ -19,7 +19,10 @@ import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_ui.extensions.setImageOrNull
import com.anytypeio.anytype.core_ui.features.dataview.*
import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridAdapter
import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridHeaderAdapter
import com.anytypeio.anytype.core_ui.features.dataview.ViewerListAdapter
import com.anytypeio.anytype.core_ui.features.dataview.ViewerTypeAdapter
import com.anytypeio.anytype.core_ui.reactive.*
import com.anytypeio.anytype.core_utils.OnSwipeListener
import com.anytypeio.anytype.core_utils.ext.argString
@ -73,12 +76,6 @@ open class ObjectSetFragment :
GestureDetector(context, swipeListener)
}
private val viewerTabAdapter by lazy {
ViewerTabItemAdapter(
onAddNewViewerClicked = { vm.onCreateNewViewerClicked() },
onViewerTabClicked = { vm.onViewerTabClicked(it) }
)
}
private val viewerGridHeaderAdapter by lazy {
ViewerGridHeaderAdapter(
onCreateNewColumnClicked = { vm.onAddNewDataViewRelation() }
@ -345,7 +342,6 @@ open class ObjectSetFragment :
super.onStart()
jobs += lifecycleScope.subscribe(vm.commands) { observeCommands(it) }
jobs += lifecycleScope.subscribe(vm.header.filterNotNull()) { observeHeader(it) }
jobs += lifecycleScope.subscribe(vm.viewerTabs) { viewerTabAdapter.update(it) }
jobs += lifecycleScope.subscribe(vm.viewerGrid) { observeGrid(it) }
vm.onStart(ctx)
}

View file

@ -5,33 +5,28 @@ import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.features.dataview.diff.GridRowDiffUtil
import com.anytypeio.anytype.presentation.sets.CellAction
import com.anytypeio.anytype.presentation.sets.model.CellView
import com.anytypeio.anytype.presentation.sets.model.Viewer
import kotlinx.android.synthetic.main.item_viewer_grid_row.view.*
import timber.log.Timber
class ViewerGridAdapter(
private var items: List<Viewer.GridView.Row> = emptyList(),
private val onCellClicked: (CellView) -> Unit,
private val onCellAction: (CellAction) -> Unit,
private val onObjectHeaderClicked: (String, String) -> Unit
) : RecyclerView.Adapter<ViewerGridAdapter.RecordHolder>() {
) : ListAdapter<Viewer.GridView.Row, ViewerGridAdapter.RecordHolder>(GridDiffUtil) {
var recordNamePositionX = 0f
fun update(update: List<Viewer.GridView.Row>) {
val diff = DiffUtil.calculateDiff(GridRowDiffUtil(old = items, new = update))
items = update
diff.dispatchUpdatesTo(this)
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RecordHolder {
Timber.d("OnCreateViewHolder")
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.item_viewer_grid_row, parent, false)
view.rowCellRecycler.apply {
@ -43,16 +38,14 @@ class ViewerGridAdapter(
}
return RecordHolder(view).apply {
itemView.headerContainer.setOnClickListener {
val item = items[bindingAdapterPosition]
val item = getItem(bindingAdapterPosition)
onObjectHeaderClicked(item.id, item.type)
}
}
}
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: RecordHolder, position: Int) {
holder.bind(items[position])
holder.bind(getItem(position))
}
override fun onViewAttachedToWindow(holder: RecordHolder) {
@ -72,6 +65,7 @@ class ViewerGridAdapter(
fun bind(
row: Viewer.GridView.Row
) {
Timber.d("Binding record holder")
itemView.objectIcon.setIcon(
emoji = row.emoji,
image = row.image,
@ -81,4 +75,15 @@ class ViewerGridAdapter(
adapter.update(row.cells)
}
}
object GridDiffUtil : DiffUtil.ItemCallback<Viewer.GridView.Row>() {
override fun areItemsTheSame(
oldItem: Viewer.GridView.Row,
newItem: Viewer.GridView.Row
): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: Viewer.GridView.Row,
newItem: Viewer.GridView.Row
): Boolean = oldItem == newItem
}
}

View file

@ -9,21 +9,24 @@ import com.anytypeio.anytype.core_ui.features.dataview.diff.CellViewDiffUtil
import com.anytypeio.anytype.core_ui.features.dataview.holders.*
import com.anytypeio.anytype.presentation.sets.CellAction
import com.anytypeio.anytype.presentation.sets.model.CellView
import timber.log.Timber
class ViewerGridCellsAdapter(
private var cells: List<CellView> = listOf(),
var cells: List<CellView> = listOf(),
private val onCellClicked: (CellView) -> Unit,
private val onCellAction: (CellAction) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
fun update(update: List<CellView>) {
Timber.d("Updating cells: update size - ${update.size}, current - ${cells.size}")
// TODO maybe disable detectMoves
val diff = DiffUtil.calculateDiff(CellViewDiffUtil(old = cells, new = update))
val diff = DiffUtil.calculateDiff(CellViewDiffUtil(old = cells, new = update), false)
cells = update
diff.dispatchUpdatesTo(this)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
Timber.d("onCreateViewHolder")
val inflater = LayoutInflater.from(parent.context)
//todo Take cells width from columns width property
return when (viewType) {
@ -173,6 +176,7 @@ class ViewerGridCellsAdapter(
override fun getItemCount(): Int = cells.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
Timber.d("onBindViewHolder")
when (holder) {
is DVGridCellDescriptionHolder -> holder.bind(cells[position] as CellView.Description)
is DVGridCellDateHolder -> holder.bind(cells[position] as CellView.Date)

View file

@ -1,69 +1,88 @@
package com.anytypeio.anytype.core_ui.features.dataview
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.common.AbstractAdapter
import com.anytypeio.anytype.core_ui.common.AbstractViewHolder
import com.anytypeio.anytype.presentation.sets.model.ColumnView
import kotlinx.android.synthetic.main.viewer_cell.view.*
import timber.log.Timber
class ViewerGridHeaderAdapter(
items: List<ColumnView> = emptyList(),
val onCreateNewColumnClicked: () -> Unit,
) : AbstractAdapter<ColumnView>(items) {
) : ListAdapter<ColumnView, ViewerGridHeaderAdapter.HeaderViewHolder>(ColumnHeaderDiffCallback) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): AbstractViewHolder<ColumnView> = when (viewType) {
HEADER_TYPE -> {
DefaultHolder(
view = inflate(parent, R.layout.item_grid_column_header)
)
}
PLUS_TYPE -> {
PlusHolder(
view = inflate(parent, R.layout.item_grid_column_header_plus)
).apply {
itemView.setOnClickListener {
onCreateNewColumnClicked()
}
): HeaderViewHolder = when (viewType) {
HEADER_TYPE -> HeaderViewHolder.DefaultHolder.create(parent)
PLUS_TYPE -> HeaderViewHolder.PlusHolder.create(parent).apply {
itemView.setOnClickListener {
onCreateNewColumnClicked()
}
}
else -> throw IllegalStateException("Unexpected view type: $viewType")
}
override fun onBindViewHolder(holder: AbstractViewHolder<ColumnView>, position: Int) {
if (position < items.size) super.onBindViewHolder(holder, position)
override fun onBindViewHolder(holder: HeaderViewHolder, position: Int) {
if (holder is HeaderViewHolder.DefaultHolder) holder.bind(getItem(position))
}
override fun getItemViewType(position: Int) = if (position == items.size) {
override fun getItemViewType(position: Int) = if (position == super.getItemCount()) {
PLUS_TYPE
} else {
HEADER_TYPE
}
override fun getItemCount(): Int {
return if (super.getItemCount() == 0)
0
else
super.getItemCount() + 1
}
override fun getItemCount(): Int = if (super.getItemCount() == 0) 0 else super.getItemCount() + 1
class DefaultHolder(view: View) : AbstractViewHolder<ColumnView>(view) {
override fun bind(item: ColumnView) {
itemView.cellText.text = item.text
sealed class HeaderViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class DefaultHolder(view: View) : HeaderViewHolder(view) {
fun bind(item: ColumnView) {
Timber.d("Binding default holder")
itemView.cellText.text = item.text
}
companion object {
fun create(
parent: ViewGroup
): DefaultHolder = DefaultHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_grid_column_header,
parent,
false
)
)
}
}
class PlusHolder(view: View) : HeaderViewHolder(view) {
companion object {
fun create(
parent: ViewGroup
): PlusHolder = PlusHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_grid_column_header_plus,
parent,
false
)
)
}
}
}
class PlusHolder(view: View) : AbstractViewHolder<ColumnView>(view) {
override fun bind(item: ColumnView) {}
}
override fun update(update: List<ColumnView>) {
items = update
notifyDataSetChanged()
object ColumnHeaderDiffCallback : DiffUtil.ItemCallback<ColumnView>() {
override fun areItemsTheSame(
oldItem: ColumnView,
newItem: ColumnView
): Boolean = oldItem.key == newItem.key
override fun areContentsTheSame(
oldItem: ColumnView,
newItem: ColumnView
): Boolean = oldItem == newItem
}
companion object {

View file

@ -52,6 +52,7 @@ class ViewerTypeAdapter(
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
Timber.d("onBindViewHolder")
when (holder) {
is GridHolder -> holder.bind(
viewer = items[position] as Viewer.GridView,
@ -89,11 +90,18 @@ class ViewerTypeAdapter(
headerAdapter: ViewerGridHeaderAdapter
) {
Timber.d("Binding grid")
headerAdapter.update(viewer.columns)
gridAdapter.update(viewer.rows)
if (columns.adapter == null) columns.adapter = headerAdapter
if (rows.adapter == null) rows.adapter = gridAdapter
if (columns.adapter == null) {
Timber.d("Setting columns adapter")
columns.adapter = headerAdapter
}
if (rows.adapter == null) {
Timber.d("Setting rows adapter")
rows.adapter = gridAdapter
}
headerAdapter.submitList(viewer.columns)
gridAdapter.submitList(viewer.rows)
itemView.horizontalScrollView.setOnScrollChangeListener { _, scrollX, _, _, _ ->
val translationX = scrollX.toFloat()
@ -106,7 +114,6 @@ class ViewerTypeAdapter(
}
class ListHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(adapter: ViewerListAdapter) {
itemView.rvRows.adapter = adapter
}

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.core_ui.features.dataview.diff
import androidx.recyclerview.widget.DiffUtil
import com.anytypeio.anytype.presentation.sets.model.CellView
import timber.log.Timber
class CellViewDiffUtil(
private val old: List<CellView>,
@ -11,13 +12,13 @@ class CellViewDiffUtil(
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = old[oldItemPosition]
val newItem = new[newItemPosition]
return (oldItem.id == newItem.id)
return (oldItem.id == newItem.id).also { Timber.d("areItemsTheSame: $it") }
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = old[oldItemPosition]
val newItem = new[newItemPosition]
return oldItem == newItem
return oldItem == newItem.also { Timber.d("areContentsTheSame: $it") }
}
override fun getOldListSize(): Int = old.size

View file

@ -17,7 +17,11 @@ class GridRowDiffUtil(
override fun areContentsTheSame(
oldItemPosition: Int,
newItemPosition: Int
): Boolean = false
): Boolean {
val oldItem = old[oldItemPosition]
val newItem = new[newItemPosition]
return oldItem == newItem
}
override fun getOldListSize(): Int = old.size
override fun getNewListSize(): Int = new.size