Use coroutines for drag and drop differ

pull/1715/head
Alex Baker 3 years ago
parent da967afaf5
commit fe5f6b4e35

@ -184,7 +184,6 @@ dependencies {
implementation("androidx.room:room-ktx:${Versions.room}") implementation("androidx.room:room-ktx:${Versions.room}")
kapt("androidx.room:room-compiler:${Versions.room}") kapt("androidx.room:room-compiler:${Versions.room}")
implementation("androidx.appcompat:appcompat:1.3.1") implementation("androidx.appcompat:appcompat:1.3.1")
implementation("io.reactivex.rxjava2:rxandroid:2.1.1")
implementation("androidx.paging:paging-runtime:2.1.2") implementation("androidx.paging:paging-runtime:2.1.2")
implementation("io.noties.markwon:core:${Versions.markwon}") implementation("io.noties.markwon:core:${Versions.markwon}")
implementation("io.noties.markwon:editor:${Versions.markwon}") implementation("io.noties.markwon:editor:${Versions.markwon}")

@ -189,12 +189,6 @@
license: The Apache Software License, Version 2.0 license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html url: http://developer.android.com/tools/extras/support-library.html
- artifact: io.reactivex.rxjava2:rxandroid:+
name: RxAndroid
copyrightHolder: The RxAndroid authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/ReactiveX/RxAndroid
- artifact: androidx.swiperefreshlayout:swiperefreshlayout:+ - artifact: androidx.swiperefreshlayout:swiperefreshlayout:+
name: Android Support Library Custom View name: Android Support Library Custom View
copyrightHolder: Android Open Source Project copyrightHolder: Android Open Source Project
@ -274,12 +268,6 @@
license: The Apache Software License, Version 2.0 license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html url: http://developer.android.com/tools/extras/support-library.html
- artifact: org.reactivestreams:reactive-streams:+
name: reactive-streams
copyrightHolder: Public domain
license: CC0
licenseUrl: http://creativecommons.org/publicdomain/zero/1.0/
url: http://www.reactive-streams.org/
- artifact: androidx.work:work-runtime:+ - artifact: androidx.work:work-runtime:+
name: Android WorkManager Runtime name: Android WorkManager Runtime
copyrightHolder: Android Open Source Project copyrightHolder: Android Open Source Project
@ -333,12 +321,6 @@
license: The Apache Software License, Version 2.0 license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html url: http://developer.android.com/tools/extras/support-library.html
- artifact: io.reactivex.rxjava2:rxjava:+
name: RxJava
copyrightHolder: RxJava Contributors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/ReactiveX/RxJava
- artifact: com.google.apis:google-api-services-tasks:+ - artifact: com.google.apis:google-api-services-tasks:+
name: Tasks API v1-rev55-1.25.0 name: Tasks API v1-rev55-1.25.0
copyrightHolder: Google Inc. copyrightHolder: Google Inc.

@ -455,20 +455,6 @@
"url": "http://developer.android.com/tools/extras/support-library.html", "url": "http://developer.android.com/tools/extras/support-library.html",
"libraryName": "Android Support Library Custom View" "libraryName": "Android Support Library Custom View"
}, },
{
"artifactId": {
"name": "rxandroid",
"group": "io.reactivex.rxjava2",
"version": "+"
},
"copyrightHolder": "The RxAndroid authors",
"copyrightStatement": "Copyright © The RxAndroid authors. All rights reserved.",
"license": "The Apache Software License, Version 2.0",
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt",
"normalizedLicense": "apache2",
"url": "https://github.com/ReactiveX/RxAndroid",
"libraryName": "RxAndroid"
},
{ {
"artifactId": { "artifactId": {
"name": "swiperefreshlayout", "name": "swiperefreshlayout",
@ -651,20 +637,6 @@
"url": "http://developer.android.com/tools/extras/support-library.html", "url": "http://developer.android.com/tools/extras/support-library.html",
"libraryName": "Android Support VectorDrawable" "libraryName": "Android Support VectorDrawable"
}, },
{
"artifactId": {
"name": "reactive-streams",
"group": "org.reactivestreams",
"version": "+"
},
"copyrightHolder": "Public domain",
"copyrightStatement": "Copyright © Public domain. All rights reserved.",
"license": "CC0",
"licenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/",
"normalizedLicense": "cc0",
"url": "http://www.reactive-streams.org/",
"libraryName": "reactive-streams"
},
{ {
"artifactId": { "artifactId": {
"name": "work-runtime", "name": "work-runtime",
@ -790,20 +762,6 @@
"url": "http://developer.android.com/tools/extras/support-library.html", "url": "http://developer.android.com/tools/extras/support-library.html",
"libraryName": "Android Support Library Drawer Layout" "libraryName": "Android Support Library Drawer Layout"
}, },
{
"artifactId": {
"name": "rxjava",
"group": "io.reactivex.rxjava2",
"version": "+"
},
"copyrightHolder": "RxJava Contributors",
"copyrightStatement": "Copyright © RxJava Contributors. All rights reserved.",
"license": "The Apache Software License, Version 2.0",
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt",
"normalizedLicense": "apache2",
"url": "https://github.com/ReactiveX/RxJava",
"libraryName": "RxJava"
},
{ {
"artifactId": { "artifactId": {
"name": "google-api-services-tasks", "name": "google-api-services-tasks",

@ -14,11 +14,10 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterListItem import com.todoroo.astrid.api.FilterListItem
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.flow.MutableSharedFlow
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.activities.DragAndDropDiffer import org.tasks.activities.DragAndDropDiffer
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
@ -46,13 +45,12 @@ class NavigationDrawerAdapter @Inject constructor(
private lateinit var onClick: (FilterListItem?) -> Unit private lateinit var onClick: (FilterListItem?) -> Unit
private var selected: Filter? = null private var selected: Filter? = null
override val disposables = CompositeDisposable() override val flow = MutableSharedFlow<MutableList<FilterListItem>>()
override val publishSubject = PublishSubject.create<MutableList<FilterListItem>>()
override val updates: Queue<Pair<MutableList<FilterListItem>, DiffUtil.DiffResult?>> = LinkedList() override val updates: Queue<Pair<MutableList<FilterListItem>, DiffUtil.DiffResult?>> = LinkedList()
override val scope: CoroutineScope =
CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job())
override var items = initializeDiffer(ArrayList()) override var items = initializeDiffer(ArrayList())
override var dragging = false override var dragging = false
override val scope: CoroutineScope =
CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job())
fun setOnClick(onClick: (FilterListItem?) -> Unit) { fun setOnClick(onClick: (FilterListItem?) -> Unit) {
this.onClick = onClick this.onClick = onClick

@ -3,19 +3,14 @@ package org.tasks.activities
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListUpdateCallback import androidx.recyclerview.widget.ListUpdateCallback
import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.AndroidUtilities
import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.coroutines.*
import io.reactivex.disposables.CompositeDisposable import kotlinx.coroutines.flow.*
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.util.* import java.util.*
import java.util.concurrent.Executors
interface DragAndDropDiffer<T, R> : ListUpdateCallback { interface DragAndDropDiffer<T, R> : ListUpdateCallback {
val publishSubject: PublishSubject<R> val flow: MutableSharedFlow<R>
val updates: Queue<Pair<R, DiffUtil.DiffResult?>> val updates: Queue<Pair<R, DiffUtil.DiffResult?>>
val disposables: CompositeDisposable
var items: R var items: R
var dragging: Boolean var dragging: Boolean
val scope: CoroutineScope val scope: CoroutineScope
@ -23,7 +18,7 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
fun submitList(list: List<T>) { fun submitList(list: List<T>) {
scope.launch { scope.launch {
val transform = transform(list) val transform = transform(list)
publishSubject.onNext(transform) flow.emit(transform)
} }
} }
@ -50,16 +45,18 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
} }
} }
@ExperimentalCoroutinesApi
fun initializeDiffer(list: List<T>): R { fun initializeDiffer(list: List<T>): R {
val initial = transform(list) val initial = transform(list)
disposables.add(publishSubject scope.launch(Dispatchers.Main) {
.observeOn(Schedulers.single()) flow
.scan(Pair(initial, null), { last: Pair<R, DiffUtil.DiffResult?>, next: R -> .scan(Pair(initial, null), { last: Pair<R, DiffUtil.DiffResult?>, next: R ->
calculateDiff(last, next) calculateDiff(last, next)
}) })
.skip(1) .drop(1)
.observeOn(AndroidSchedulers.mainThread()) .flowOn(Executors.newSingleThreadExecutor().asCoroutineDispatcher())
.subscribe(this::applyDiff)) .collect { applyDiff(it) }
}
return initial return initial
} }
@ -68,7 +65,6 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
fun diff(last: R, next: R): DiffUtil.DiffResult fun diff(last: R, next: R): DiffUtil.DiffResult
fun dispose() { fun dispose() {
disposables.dispose()
scope.cancel() scope.cancel()
} }
} }

@ -10,11 +10,10 @@ import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.adapter.TaskAdapter import com.todoroo.astrid.adapter.TaskAdapter
import com.todoroo.astrid.utility.Flags import com.todoroo.astrid.utility.Flags
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.tasks.activities.DragAndDropDiffer import org.tasks.activities.DragAndDropDiffer
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
@ -40,13 +39,12 @@ class DragAndDropRecyclerAdapter(
private val itemTouchHelper = ItemTouchHelper(ItemTouchHelperCallback()).apply { private val itemTouchHelper = ItemTouchHelper(ItemTouchHelperCallback()).apply {
attachToRecyclerView(recyclerView) attachToRecyclerView(recyclerView)
} }
override val publishSubject = PublishSubject.create<SectionedDataSource>() override val flow = MutableSharedFlow<SectionedDataSource>()
override val disposables = CompositeDisposable()
override val updates: Queue<Pair<SectionedDataSource, DiffUtil.DiffResult?>> = LinkedList() override val updates: Queue<Pair<SectionedDataSource, DiffUtil.DiffResult?>> = LinkedList()
override var dragging = false override var dragging = false
override var items = initializeDiffer(tasks)
override val scope: CoroutineScope = override val scope: CoroutineScope =
CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job()) CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job())
override var items = initializeDiffer(tasks)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val viewType = getItemViewType(position) val viewType = getItemViewType(position)

Loading…
Cancel
Save