From 73f01fb08b47b7a05586938d2eb4193b9a14326e Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Fri, 22 Nov 2019 15:54:12 -0600 Subject: [PATCH] Remove paging library --- app/build.gradle.kts | 1 - app/licenses.yml | 12 -- app/src/main/assets/licenses.json | 32 ----- .../astrid/activity/TaskListFragment.java | 24 ++-- .../java/com/todoroo/astrid/dao/TaskDao.java | 7 -- .../tasklist/ItemTouchHelperCallback.java | 4 +- .../tasklist/ManualSortRecyclerAdapter.java | 110 ------------------ .../tasklist/PagedListRecyclerAdapter.java | 47 -------- .../tasklist/TaskListRecyclerAdapter.java | 100 ++++++++++++++-- .../java/org/tasks/ui/TaskListViewModel.java | 50 +------- 10 files changed, 107 insertions(+), 280 deletions(-) delete mode 100644 app/src/main/java/org/tasks/tasklist/ManualSortRecyclerAdapter.java delete mode 100644 app/src/main/java/org/tasks/tasklist/PagedListRecyclerAdapter.java diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 76bb6f473..a0dbcbdfc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -141,7 +141,6 @@ dependencies { annotationProcessor("androidx.room:room-compiler:${Versions.room}") implementation("androidx.lifecycle:lifecycle-extensions:2.1.0") implementation("io.reactivex.rxjava2:rxandroid:2.1.1") - implementation("androidx.paging:paging-runtime:2.1.0") annotationProcessor("com.jakewharton:butterknife-compiler:${Versions.butterknife}") implementation("com.jakewharton:butterknife:${Versions.butterknife}") diff --git a/app/licenses.yml b/app/licenses.yml index 37104bab8..f1ebbadb8 100644 --- a/app/licenses.yml +++ b/app/licenses.yml @@ -692,18 +692,6 @@ license: The Apache Software License, Version 2.0 licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt url: https://github.com/census-instrumentation/opencensus-java -- artifact: androidx.paging:paging-common:+ - name: Android Paging-Common - copyrightHolder: Android Open Source Project - license: The Apache Software License, Version 2.0 - licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt - url: https://developer.android.com/topic/libraries/architecture/index.html -- artifact: androidx.paging:paging-runtime:+ - name: Android Paging-Runtime - copyrightHolder: Android Open Source Project - license: The Apache Software License, Version 2.0 - licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt - url: https://developer.android.com/topic/libraries/architecture/index.html - artifact: org.ogce:xpp3:+ skip: true - artifact: junit:junit:+ diff --git a/app/src/main/assets/licenses.json b/app/src/main/assets/licenses.json index 471cece10..27dbed9a4 100644 --- a/app/src/main/assets/licenses.json +++ b/app/src/main/assets/licenses.json @@ -1872,38 +1872,6 @@ "version": "0.19.2" } }, - { - "notice": null, - "copyrightHolder": "Android Open Source Project", - "copyrightStatement": "Copyright © Android Open Source Project. All rights reserved.", - "license": "The Apache Software License, Version 2.0", - "licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt", - "normalizedLicense": "apache2", - "year": null, - "url": "https://developer.android.com/topic/libraries/architecture/index.html", - "libraryName": "Android Paging-Common", - "artifactId": { - "name": "paging-common", - "group": "androidx.paging", - "version": "2.1.0" - } - }, - { - "notice": null, - "copyrightHolder": "Android Open Source Project", - "copyrightStatement": "Copyright © Android Open Source Project. All rights reserved.", - "license": "The Apache Software License, Version 2.0", - "licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt", - "normalizedLicense": "apache2", - "year": null, - "url": "https://developer.android.com/topic/libraries/architecture/index.html", - "libraryName": "Android Paging-Runtime", - "artifactId": { - "name": "paging-runtime", - "group": "androidx.paging", - "version": "2.1.0" - } - }, { "notice": null, "copyrightHolder": "Android Open Source Project", diff --git a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java index 5f1c44c97..003061249 100644 --- a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java +++ b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java @@ -87,8 +87,6 @@ import org.tasks.preferences.Device; import org.tasks.preferences.Preferences; import org.tasks.sync.SyncAdapters; import org.tasks.tasklist.ActionModeProvider; -import org.tasks.tasklist.ManualSortRecyclerAdapter; -import org.tasks.tasklist.PagedListRecyclerAdapter; import org.tasks.tasklist.TaskListRecyclerAdapter; import org.tasks.tasklist.ViewHolderFactory; import org.tasks.ui.MenuColorizer; @@ -259,21 +257,13 @@ public final class TaskListFragment extends InjectingFragment taskAdapter.supportsParentingOrManualSort()); recyclerAdapter = - taskAdapter.supportsParentingOrManualSort() - ? new ManualSortRecyclerAdapter( - taskAdapter, - recyclerView, - viewHolderFactory, - this, - actionModeProvider, - taskListViewModel.getValue()) - : new PagedListRecyclerAdapter( - taskAdapter, - recyclerView, - viewHolderFactory, - this, - actionModeProvider, - taskListViewModel.getValue()); + new TaskListRecyclerAdapter( + taskAdapter, + recyclerView, + viewHolderFactory, + this, + actionModeProvider, + taskListViewModel.getValue()); taskAdapter.setHelper(recyclerAdapter); ((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); recyclerView.setLayoutManager(new LinearLayoutManager(context)); diff --git a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java index 2e941b35d..bcd505983 100644 --- a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java +++ b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java @@ -9,7 +9,6 @@ package com.todoroo.astrid.dao; import static com.todoroo.andlib.utility.DateUtilities.now; import android.database.Cursor; -import androidx.paging.DataSource; import androidx.room.Dao; import androidx.room.Insert; import androidx.room.Query; @@ -25,9 +24,6 @@ import com.todoroo.astrid.helper.UUIDHelper; import java.util.ArrayList; import java.util.List; import org.tasks.BuildConfig; -import org.tasks.data.CaldavTask; -import org.tasks.data.GoogleTask; -import org.tasks.data.Tag; import org.tasks.data.TaskContainer; import org.tasks.jobs.WorkManager; import timber.log.Timber; @@ -133,9 +129,6 @@ public abstract class TaskDao { @RawQuery public abstract List fetchTasks(SimpleSQLiteQuery query); - @RawQuery(observedEntities = {Task.class, GoogleTask.class, CaldavTask.class, Tag.class}) - public abstract DataSource.Factory getTaskFactory(SimpleSQLiteQuery query); - @Query("UPDATE tasks SET modified = datetime('now', 'localtime') WHERE _id in (:ids)") public abstract void touch(List ids); diff --git a/app/src/main/java/org/tasks/tasklist/ItemTouchHelperCallback.java b/app/src/main/java/org/tasks/tasklist/ItemTouchHelperCallback.java index 4b5e811a6..8d5dd887e 100644 --- a/app/src/main/java/org/tasks/tasklist/ItemTouchHelperCallback.java +++ b/app/src/main/java/org/tasks/tasklist/ItemTouchHelperCallback.java @@ -15,14 +15,14 @@ import org.tasks.data.TaskContainer; public class ItemTouchHelperCallback extends ItemTouchHelper.Callback { private final TaskAdapter adapter; - private final ManualSortRecyclerAdapter recyclerAdapter; + private final TaskListRecyclerAdapter recyclerAdapter; private final Runnable onClear; private int from = -1; private int to = -1; private boolean dragging; ItemTouchHelperCallback( - TaskAdapter adapter, ManualSortRecyclerAdapter recyclerAdapter, Runnable onClear) { + TaskAdapter adapter, TaskListRecyclerAdapter recyclerAdapter, Runnable onClear) { this.adapter = adapter; this.recyclerAdapter = recyclerAdapter; this.onClear = onClear; diff --git a/app/src/main/java/org/tasks/tasklist/ManualSortRecyclerAdapter.java b/app/src/main/java/org/tasks/tasklist/ManualSortRecyclerAdapter.java deleted file mode 100644 index ea0ee2126..000000000 --- a/app/src/main/java/org/tasks/tasklist/ManualSortRecyclerAdapter.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.tasks.tasklist; - -import static com.todoroo.andlib.utility.AndroidUtilities.assertMainThread; -import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread; - -import androidx.annotation.NonNull; -import androidx.core.util.Pair; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.DiffUtil.DiffResult; -import androidx.recyclerview.widget.ItemTouchHelper; -import androidx.recyclerview.widget.ListUpdateCallback; -import androidx.recyclerview.widget.RecyclerView; -import com.todoroo.astrid.activity.TaskListFragment; -import com.todoroo.astrid.adapter.TaskAdapter; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.schedulers.Schedulers; -import io.reactivex.subjects.PublishSubject; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import org.tasks.data.TaskContainer; - -public class ManualSortRecyclerAdapter extends TaskListRecyclerAdapter { - - private final ItemTouchHelperCallback itemTouchHelperCallback; - private List list; - private PublishSubject> publishSubject = PublishSubject.create(); - private CompositeDisposable disposables = new CompositeDisposable(); - private Queue, DiffResult>> updates = new LinkedList<>(); - - public ManualSortRecyclerAdapter( - TaskAdapter adapter, - RecyclerView recyclerView, - ViewHolderFactory viewHolderFactory, - TaskListFragment taskList, - ActionModeProvider actionModeProvider, - List list) { - super(adapter, recyclerView, viewHolderFactory, taskList, actionModeProvider); - this.list = list; - itemTouchHelperCallback = new ItemTouchHelperCallback(adapter, this, this::drainQueue); - new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView); - Pair, DiffResult> initial = Pair.create(list, null); - disposables.add( - publishSubject - .observeOn(Schedulers.computation()) - .scan(initial, this::calculateDiff) - .skip(1) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::applyDiff)); - } - - private Pair, DiffResult> calculateDiff( - Pair, DiffResult> last, List next) { - assertNotMainThread(); - - DiffCallback cb = new DiffCallback(last.first, next, adapter); - DiffResult result = DiffUtil.calculateDiff(cb, true); - - return Pair.create(next, result); - } - - private void applyDiff(Pair, DiffResult> update) { - assertMainThread(); - - updates.add(update); - - if (!itemTouchHelperCallback.isDragging()) { - drainQueue(); - } - } - - private void drainQueue() { - assertMainThread(); - - Pair, DiffResult> update = updates.poll(); - while (update != null) { - list = update.first; - update.second.dispatchUpdatesTo((ListUpdateCallback) this); - update = updates.poll(); - } - } - - @Override - public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) { - disposables.dispose(); - } - - @Override - public int getItemCount() { - return list.size(); - } - - @Override - public TaskContainer getItem(int position) { - return list.get(position); - } - - @Override - public void submitList(List list) { - publishSubject.onNext(list); - } - - void moved(int from, int to, int indent) { - adapter.moved(from, to, indent); - TaskContainer task = list.remove(from); - list.add(from < to ? to - 1 : to, task); - taskList.loadTaskListContent(); - } -} diff --git a/app/src/main/java/org/tasks/tasklist/PagedListRecyclerAdapter.java b/app/src/main/java/org/tasks/tasklist/PagedListRecyclerAdapter.java deleted file mode 100644 index 1544a706e..000000000 --- a/app/src/main/java/org/tasks/tasklist/PagedListRecyclerAdapter.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.tasks.tasklist; - -import androidx.paging.AsyncPagedListDiffer; -import androidx.paging.PagedList; -import androidx.recyclerview.widget.AsyncDifferConfig; -import androidx.recyclerview.widget.RecyclerView; -import com.todoroo.astrid.activity.TaskListFragment; -import com.todoroo.astrid.adapter.TaskAdapter; -import java.util.List; -import org.tasks.data.TaskContainer; - -public class PagedListRecyclerAdapter extends TaskListRecyclerAdapter { - - private AsyncPagedListDiffer differ; - - public PagedListRecyclerAdapter( - TaskAdapter adapter, - RecyclerView recyclerView, - ViewHolderFactory viewHolderFactory, - TaskListFragment taskList, - ActionModeProvider actionModeProvider, - List list) { - super(adapter, recyclerView, viewHolderFactory, taskList, actionModeProvider); - - differ = - new AsyncPagedListDiffer<>( - this, new AsyncDifferConfig.Builder<>(new ItemCallback()).build()); - if (list instanceof PagedList) { - differ.submitList((PagedList) list); - } - } - - @Override - public int getItemCount() { - return differ.getItemCount(); - } - - @Override - public TaskContainer getItem(int position) { - return differ.getItem(position); - } - - @Override - public void submitList(List list) { - differ.submitList((PagedList) list); - } -} diff --git a/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java b/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java index 4231d501e..886b92810 100644 --- a/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java +++ b/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java @@ -1,11 +1,18 @@ package org.tasks.tasklist; +import static com.todoroo.andlib.utility.AndroidUtilities.assertMainThread; +import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread; + import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.view.ActionMode; +import androidx.core.util.Pair; import androidx.fragment.app.FragmentActivity; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.DiffUtil.DiffResult; +import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.RecyclerView; @@ -15,34 +22,59 @@ import com.todoroo.astrid.api.CaldavFilter; import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.GtasksFilter; import com.todoroo.astrid.utility.Flags; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; +import io.reactivex.subjects.PublishSubject; +import java.util.LinkedList; import java.util.List; import java.util.Objects; +import java.util.Queue; import org.tasks.data.TaskContainer; import org.tasks.intents.TaskIntents; -public abstract class TaskListRecyclerAdapter extends RecyclerView.Adapter +public class TaskListRecyclerAdapter extends RecyclerView.Adapter implements ViewHolder.ViewHolderCallbacks, ListUpdateCallback { - protected final TaskAdapter adapter; - final TaskListFragment taskList; + private final TaskAdapter adapter; + private final TaskListFragment taskList; private final RecyclerView recyclerView; private final ViewHolderFactory viewHolderFactory; private final ActionModeProvider actionModeProvider; private final boolean isRemoteList; + private final ItemTouchHelperCallback itemTouchHelperCallback; private ActionMode mode = null; + private List list; + private PublishSubject> publishSubject = PublishSubject.create(); + private CompositeDisposable disposables = new CompositeDisposable(); + private Queue, DiffResult>> updates = new LinkedList<>(); - TaskListRecyclerAdapter( + public TaskListRecyclerAdapter( TaskAdapter adapter, RecyclerView recyclerView, ViewHolderFactory viewHolderFactory, TaskListFragment taskList, - ActionModeProvider actionModeProvider) { + ActionModeProvider actionModeProvider, + List list) { this.adapter = adapter; this.recyclerView = recyclerView; this.viewHolderFactory = viewHolderFactory; this.taskList = taskList; this.actionModeProvider = actionModeProvider; - isRemoteList = taskList.getFilter() instanceof GtasksFilter || taskList.getFilter() instanceof CaldavFilter; + isRemoteList = + taskList.getFilter() instanceof GtasksFilter + || taskList.getFilter() instanceof CaldavFilter; + this.list = list; + itemTouchHelperCallback = new ItemTouchHelperCallback(adapter, this, this::drainQueue); + new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView); + Pair, DiffResult> initial = Pair.create(list, null); + disposables.add( + publishSubject + .observeOn(Schedulers.computation()) + .scan(initial, this::calculateDiff) + .skip(1) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::applyDiff)); } @NonNull @@ -141,9 +173,13 @@ public abstract class TaskListRecyclerAdapter extends RecyclerView.Adapter list); + public void submitList(List list) { + publishSubject.onNext(list); + } @Override public void onInserted(int position, int count) { @@ -175,4 +211,52 @@ public abstract class TaskListRecyclerAdapter extends RecyclerView.Adapter, DiffResult> calculateDiff( + Pair, DiffResult> last, List next) { + assertNotMainThread(); + + DiffCallback cb = new DiffCallback(last.first, next, adapter); + DiffResult result = DiffUtil.calculateDiff(cb, true); + + return Pair.create(next, result); + } + + private void applyDiff(Pair, DiffResult> update) { + assertMainThread(); + + updates.add(update); + + if (!itemTouchHelperCallback.isDragging()) { + drainQueue(); + } + } + + private void drainQueue() { + assertMainThread(); + + Pair, DiffResult> update = updates.poll(); + while (update != null) { + list = update.first; + update.second.dispatchUpdatesTo((ListUpdateCallback) this); + update = updates.poll(); + } + } + + @Override + public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) { + disposables.dispose(); + } + + @Override + public int getItemCount() { + return list.size(); + } + + void moved(int from, int to, int indent) { + adapter.moved(from, to, indent); + TaskContainer task = list.remove(from); + list.add(from < to ? to - 1 : to, task); + taskList.loadTaskListContent(); + } } diff --git a/app/src/main/java/org/tasks/ui/TaskListViewModel.java b/app/src/main/java/org/tasks/ui/TaskListViewModel.java index 7949e5e34..35fa92621 100644 --- a/app/src/main/java/org/tasks/ui/TaskListViewModel.java +++ b/app/src/main/java/org/tasks/ui/TaskListViewModel.java @@ -9,13 +9,9 @@ import static com.todoroo.astrid.activity.TaskListFragment.TAGS_METADATA_JOIN; import androidx.annotation.NonNull; import androidx.lifecycle.LifecycleOwner; -import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModel; -import androidx.paging.DataSource.Factory; -import androidx.paging.LivePagedListBuilder; -import androidx.paging.PagedList; import androidx.sqlite.db.SimpleSQLiteQuery; import com.google.common.collect.Lists; import com.todoroo.andlib.data.Property.StringProperty; @@ -53,10 +49,7 @@ import org.tasks.data.TaskContainer; import org.tasks.preferences.Preferences; import timber.log.Timber; -public class TaskListViewModel extends ViewModel implements Observer> { - - private static final PagedList.Config PAGED_LIST_CONFIG = - new PagedList.Config.Builder().setPageSize(20).build(); +public class TaskListViewModel extends ViewModel { private static final Table RECURSIVE = new Table("recursive_tasks"); private static final Field RECURSIVE_TASK = field(RECURSIVE + ".task"); @@ -86,7 +79,6 @@ public class TaskListViewModel extends ViewModel implements Observer> internal; public void setFilter(@NonNull Filter filter, boolean manualSort) { if (!filter.equals(this.filter) @@ -259,55 +251,25 @@ public class TaskListViewModel extends ViewModel implements Observer taskDao.fetchTasks(query)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(tasks::setValue, Timber::e)); - } else { - Factory factory = taskDao.getTaskFactory(query); - LivePagedListBuilder builder = new LivePagedListBuilder<>( - factory, PAGED_LIST_CONFIG); - List current = tasks.getValue(); - if (current instanceof PagedList) { - Object lastKey = ((PagedList) current).getLastKey(); - if (lastKey instanceof Integer) { - builder.setInitialLoadKey((Integer) lastKey); - } - } - internal = builder.build(); - internal.observeForever(this); - } + disposable.add( + Single.fromCallable(() -> taskDao.fetchTasks(query)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(tasks::setValue, Timber::e)); } @Override protected void onCleared() { disposable.dispose(); - - removeObserver(); } public List getValue() { List value = tasks.getValue(); return value != null ? value : Collections.emptyList(); } - - @Override - public void onChanged(PagedList taskContainers) { - tasks.setValue(taskContainers); - } }