Ensure DragAndDropDiffer works sequentially

pull/1064/head
Alex Baker 4 years ago
parent a2202dce41
commit 754b6c7e8c

@ -201,15 +201,13 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
(recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
recyclerView.layoutManager = LinearLayoutManager(context)
listViewModel.observe(this) {
lifecycleScope.launch {
submitList(it)
if (it.isEmpty()) {
swipeRefreshLayout.visibility = View.GONE
emptyRefreshLayout.visibility = View.VISIBLE
} else {
swipeRefreshLayout.visibility = View.VISIBLE
emptyRefreshLayout.visibility = View.GONE
}
submitList(it)
if (it.isEmpty()) {
swipeRefreshLayout.visibility = View.GONE
emptyRefreshLayout.visibility = View.VISIBLE
} else {
swipeRefreshLayout.visibility = View.VISIBLE
emptyRefreshLayout.visibility = View.GONE
}
}
setupRefresh(swipeRefreshLayout)
@ -222,8 +220,8 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
return parent
}
private suspend fun submitList(tasks: List<TaskContainer>) {
if (tasks is PagedList<*>) {
private fun submitList(tasks: List<TaskContainer>) {
if (tasks is PagedList<TaskContainer>) {
if (recyclerAdapter !is PagedListRecyclerAdapter) {
setAdapter(
PagedListRecyclerAdapter(
@ -233,7 +231,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
} else if (recyclerAdapter !is DragAndDropRecyclerAdapter) {
setAdapter(
DragAndDropRecyclerAdapter(
lifecycleScope, taskAdapter, recyclerView, viewHolderFactory, this, tasks, preferences))
taskAdapter, recyclerView, viewHolderFactory, this, tasks, preferences))
return
}
recyclerAdapter?.submitList(tasks)

@ -16,6 +16,9 @@ import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterListItem
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher
import org.tasks.LocalBroadcastManager
import org.tasks.activities.DragAndDropDiffer
import org.tasks.billing.Inventory
@ -26,6 +29,7 @@ import org.tasks.locale.Locale
import org.tasks.preferences.Preferences
import org.tasks.themes.ColorProvider
import java.util.*
import java.util.concurrent.Executors
import javax.inject.Inject
import kotlin.math.max
@ -47,6 +51,8 @@ class NavigationDrawerAdapter @Inject constructor(
override val updates: Queue<Pair<MutableList<FilterListItem>, DiffUtil.DiffResult?>> = LinkedList()
override var items = initializeDiffer(ArrayList())
override var dragging = false
override val scope: CoroutineScope =
CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job())
fun setOnClick(onClick: (FilterListItem?) -> Unit) {
this.onClick = onClick
@ -60,6 +66,10 @@ class NavigationDrawerAdapter @Inject constructor(
selected = savedInstanceState.getParcelable(TOKEN_SELECTED)
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
super.dispose()
}
override fun getItemId(position: Int) = position.toLong()
override fun getItemCount() = items.size

@ -7,8 +7,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.util.*
interface DragAndDropDiffer<T, R> : ListUpdateCallback {
@ -17,12 +18,13 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
val disposables: CompositeDisposable
var items: R
var dragging: Boolean
val scope: CoroutineScope
suspend fun submitList(list: List<T>) {
val transform = withContext(Dispatchers.Default) {
transform(list)
fun submitList(list: List<T>) {
scope.launch {
val transform = transform(list)
publishSubject.onNext(transform)
}
publishSubject.onNext(transform)
}
fun calculateDiff(last: Pair<R, DiffUtil.DiffResult?>, next: R): Pair<R, DiffUtil.DiffResult?> {
@ -51,7 +53,7 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
fun initializeDiffer(list: List<T>): R {
val initial = transform(list)
disposables.add(publishSubject
.observeOn(Schedulers.computation())
.observeOn(Schedulers.single())
.scan(Pair(initial, null), { last: Pair<R, DiffUtil.DiffResult?>, next: R ->
calculateDiff(last, next)
})
@ -64,4 +66,9 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
fun transform(list: List<T>): R
fun diff(last: R, next: R): DiffUtil.DiffResult
fun dispose() {
disposables.dispose()
scope.cancel()
}
}

@ -2,7 +2,6 @@ package org.tasks.tasklist
import android.graphics.Canvas
import android.view.ViewGroup
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.*
@ -13,16 +12,19 @@ import com.todoroo.astrid.adapter.TaskAdapter
import com.todoroo.astrid.utility.Flags
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.runBlocking
import org.tasks.activities.DragAndDropDiffer
import org.tasks.data.TaskContainer
import org.tasks.preferences.Preferences
import java.util.*
import java.util.concurrent.Executors
import kotlin.math.max
import kotlin.math.min
class DragAndDropRecyclerAdapter(
private val scope: LifecycleCoroutineScope,
private val adapter: TaskAdapter,
private val recyclerView: RecyclerView,
viewHolderFactory: ViewHolderFactory,
@ -43,6 +45,8 @@ class DragAndDropRecyclerAdapter(
override val updates: Queue<Pair<SectionedDataSource, DiffUtil.DiffResult?>> = LinkedList()
override var dragging = false
override var items = initializeDiffer(tasks)
override val scope: CoroutineScope =
CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job())
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val viewType = getItemViewType(position)
@ -59,7 +63,7 @@ class DragAndDropRecyclerAdapter(
override fun getItemViewType(position: Int) = if (items.isHeader(position)) 1 else 0
override suspend fun submitList(list: List<TaskContainer>) {
override fun submitList(list: List<TaskContainer>) {
super.submitList(list)
}
@ -95,8 +99,8 @@ class DragAndDropRecyclerAdapter(
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
super.dispose()
itemTouchHelper.attachToRecyclerView(null)
disposables.dispose()
}
override fun getTaskCount() = items.taskCount

@ -14,15 +14,17 @@ class PagedListRecyclerAdapter(
private val recyclerView: RecyclerView,
viewHolderFactory: ViewHolderFactory,
taskList: TaskListFragment,
list: List<TaskContainer>,
preferences: Preferences) : TaskListRecyclerAdapter(adapter, viewHolderFactory, taskList, preferences) {
list: PagedList<TaskContainer>,
preferences: Preferences
) : TaskListRecyclerAdapter(adapter, viewHolderFactory, taskList, preferences) {
private val differ: AsyncPagedListDiffer<TaskContainer> =
AsyncPagedListDiffer(this, AsyncDifferConfig.Builder(ItemCallback()).build())
override fun getItem(position: Int) = differ.getItem(position)
override suspend fun submitList(list: List<TaskContainer>) = differ.submitList(list as PagedList<TaskContainer>)
override fun submitList(list: List<TaskContainer>) =
differ.submitList(list as PagedList<TaskContainer>)
override fun onMoved(fromPosition: Int, toPosition: Int) {
val recyclerViewState = recyclerView.layoutManager!!.onSaveInstanceState()
@ -37,8 +39,6 @@ class PagedListRecyclerAdapter(
override fun getTaskCount() = itemCount
init {
if (list is PagedList<*>) {
differ.submitList(list as PagedList<TaskContainer>?)
}
differ.submitList(list as PagedList<TaskContainer>?)
}
}

@ -44,7 +44,7 @@ abstract class TaskListRecyclerAdapter internal constructor(
abstract fun dragAndDropEnabled(): Boolean
abstract suspend fun submitList(list: List<TaskContainer>)
abstract fun submitList(list: List<TaskContainer>)
override fun onInserted(position: Int, count: Int) {
notifyItemRangeInserted(position, count)

Loading…
Cancel
Save