mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 14:49:53 +01:00
Allow DbViewModel work on things other than lists.
This commit is contained in:
@@ -53,13 +53,9 @@ abstract class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
protected final AndroidNotificationManager notificationManager;
|
protected final AndroidNotificationManager notificationManager;
|
||||||
protected final BlogManager blogManager;
|
protected final BlogManager blogManager;
|
||||||
|
|
||||||
protected final MutableLiveData<LiveResult<List<BlogPostItem>>> blogPosts =
|
protected final MutableLiveData<LiveResult<ListUpdate>> blogPosts =
|
||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
|
|
||||||
// UI thread
|
|
||||||
@Nullable
|
|
||||||
private Boolean postAddedWasLocal = null;
|
|
||||||
|
|
||||||
BaseViewModel(Application application,
|
BaseViewModel(Application application,
|
||||||
@DatabaseExecutor Executor dbExecutor,
|
@DatabaseExecutor Executor dbExecutor,
|
||||||
LifecycleManager lifecycleManager,
|
LifecycleManager lifecycleManager,
|
||||||
@@ -147,11 +143,10 @@ abstract class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void onBlogPostItemAdded(BlogPostItem item, boolean local) {
|
private void onBlogPostItemAdded(BlogPostItem item, boolean local) {
|
||||||
List<BlogPostItem> items = addListItem(blogPosts, item);
|
List<BlogPostItem> items = addListItem(getBlogPostItems(), item);
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
Collections.sort(items);
|
Collections.sort(items);
|
||||||
postAddedWasLocal = local;
|
blogPosts.setValue(new LiveResult<>(new ListUpdate(local, items)));
|
||||||
blogPosts.setValue(new LiveResult<>(items));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,17 +163,42 @@ abstract class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LiveData<LiveResult<List<BlogPostItem>>> getBlogPosts() {
|
LiveData<LiveResult<ListUpdate>> getBlogPosts() {
|
||||||
return blogPosts;
|
return blogPosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@Nullable
|
@Nullable
|
||||||
Boolean getPostAddedWasLocalAndReset() {
|
protected List<BlogPostItem> getBlogPostItems() {
|
||||||
if (postAddedWasLocal == null) return null;
|
LiveResult<ListUpdate> value = blogPosts.getValue();
|
||||||
boolean wasLocal = postAddedWasLocal;
|
if (value == null) return null;
|
||||||
postAddedWasLocal = null;
|
ListUpdate result = value.getResultOrNull();
|
||||||
return wasLocal;
|
return result == null ? null : result.getItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class ListUpdate {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Boolean postAddedWasLocal;
|
||||||
|
private final List<BlogPostItem> items;
|
||||||
|
|
||||||
|
ListUpdate(@Nullable Boolean postAddedWasLocal,
|
||||||
|
List<BlogPostItem> items) {
|
||||||
|
this.postAddedWasLocal = postAddedWasLocal;
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return null when not a single post was added with this update.
|
||||||
|
* true when a single post was added locally and false if remotely.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Boolean getPostAddedWasLocal() {
|
||||||
|
return postAddedWasLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BlogPostItem> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
|
import org.briarproject.briar.android.blog.BaseViewModel.ListUpdate;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
|
import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
|
||||||
import org.briarproject.briar.android.sharing.ShareBlogActivity;
|
import org.briarproject.briar.android.sharing.ShareBlogActivity;
|
||||||
@@ -22,8 +23,6 @@ import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
|||||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||||
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -174,9 +173,9 @@ public class BlogFragment extends BaseFragment
|
|||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBlogPostsLoaded(List<BlogPostItem> items) {
|
private void onBlogPostsLoaded(ListUpdate update) {
|
||||||
adapter.submitList(items, () -> {
|
adapter.submitList(update.getItems(), () -> {
|
||||||
Boolean wasLocal = viewModel.getPostAddedWasLocalAndReset();
|
Boolean wasLocal = update.getPostAddedWasLocal();
|
||||||
if (wasLocal != null && wasLocal) {
|
if (wasLocal != null && wasLocal) {
|
||||||
list.scrollToPosition(0);
|
list.scrollToPosition(0);
|
||||||
displaySnackbar(R.string.blogs_blog_post_created,
|
displaySnackbar(R.string.blogs_blog_post_created,
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ class BlogViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadBlogPosts(GroupId groupId) {
|
private void loadBlogPosts(GroupId groupId) {
|
||||||
loadList(txn -> loadBlogPosts(txn, groupId), blogPosts::setValue);
|
loadFromDb(txn -> new ListUpdate(null, loadBlogPosts(txn, groupId)),
|
||||||
|
blogPosts::setValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSharingContacts(GroupId groupId) {
|
private void loadSharingContacts(GroupId groupId) {
|
||||||
|
|||||||
@@ -13,14 +13,13 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
|
import org.briarproject.briar.android.blog.BaseViewModel.ListUpdate;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
||||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||||
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
||||||
import org.briarproject.briar.api.blog.Blog;
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -101,10 +100,9 @@ public class FeedFragment extends BaseFragment
|
|||||||
list.stopPeriodicUpdate();
|
list.stopPeriodicUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBlogPostsLoaded(List<BlogPostItem> items) {
|
private void onBlogPostsLoaded(ListUpdate update) {
|
||||||
if (items.isEmpty()) list.showData();
|
adapter.submitList(update.getItems(), () -> {
|
||||||
else adapter.submitList(items, () -> {
|
Boolean wasLocal = update.getPostAddedWasLocal();
|
||||||
Boolean wasLocal = viewModel.getPostAddedWasLocalAndReset();
|
|
||||||
if (wasLocal != null && wasLocal) {
|
if (wasLocal != null && wasLocal) {
|
||||||
showSnackBar(R.string.blogs_blog_post_created);
|
showSnackBar(R.string.blogs_blog_post_created);
|
||||||
} else if (wasLocal != null) {
|
} else if (wasLocal != null) {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import org.briarproject.bramble.api.identity.IdentityManager;
|
|||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
|
|
||||||
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.briar.android.viewmodel.LiveResult;
|
import org.briarproject.briar.android.viewmodel.LiveResult;
|
||||||
@@ -34,10 +33,8 @@ import androidx.annotation.UiThread;
|
|||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
|
import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
|
||||||
|
|
||||||
@@ -70,14 +67,6 @@ class FeedViewModel extends BaseViewModel {
|
|||||||
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
|
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
|
||||||
LOG.info("Blog post added");
|
LOG.info("Blog post added");
|
||||||
onBlogPostAdded(b.getHeader(), b.isLocal());
|
onBlogPostAdded(b.getHeader(), b.isLocal());
|
||||||
} else if (e instanceof GroupAddedEvent) {
|
|
||||||
GroupAddedEvent g = (GroupAddedEvent) e;
|
|
||||||
if (g.getGroup().getClientId().equals(CLIENT_ID)) {
|
|
||||||
LOG.info("Blog added");
|
|
||||||
// TODO how can this even happen?
|
|
||||||
// added RSS feeds should trigger BlogPostAddedEvent, no?
|
|
||||||
onBlogAdded(g.getGroup().getId());
|
|
||||||
}
|
|
||||||
} else if (e instanceof GroupRemovedEvent) {
|
} else if (e instanceof GroupRemovedEvent) {
|
||||||
GroupRemovedEvent g = (GroupRemovedEvent) e;
|
GroupRemovedEvent g = (GroupRemovedEvent) e;
|
||||||
if (g.getGroup().getClientId().equals(CLIENT_ID)) {
|
if (g.getGroup().getClientId().equals(CLIENT_ID)) {
|
||||||
@@ -115,11 +104,11 @@ class FeedViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadAllBlogPosts() {
|
private void loadAllBlogPosts() {
|
||||||
loadList(this::loadAllBlogPosts, blogPosts::setValue);
|
loadFromDb(this::loadAllBlogPosts, blogPosts::setValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private List<BlogPostItem> loadAllBlogPosts(Transaction txn)
|
private ListUpdate loadAllBlogPosts(Transaction txn)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
long start = now();
|
long start = now();
|
||||||
List<BlogPostItem> posts = new ArrayList<>();
|
List<BlogPostItem> posts = new ArrayList<>();
|
||||||
@@ -128,29 +117,17 @@ class FeedViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
Collections.sort(posts);
|
Collections.sort(posts);
|
||||||
logDuration(LOG, "Loading all posts", start);
|
logDuration(LOG, "Loading all posts", start);
|
||||||
return posts;
|
return new ListUpdate(null, posts);
|
||||||
}
|
|
||||||
|
|
||||||
private void onBlogAdded(GroupId g) {
|
|
||||||
runOnDbThread(true, txn -> {
|
|
||||||
List<BlogPostItem> posts = loadBlogPosts(txn, g);
|
|
||||||
txn.attach(() -> onBlogPostItemsAdded(posts));
|
|
||||||
}, e -> logException(LOG, WARNING, e));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void onBlogPostItemsAdded(List<BlogPostItem> posts) {
|
private void onBlogRemoved(GroupId g) {
|
||||||
List<BlogPostItem> items = addListItems(blogPosts, posts);
|
List<BlogPostItem> items = removeListItems(getBlogPostItems(), item ->
|
||||||
|
item.getGroupId().equals(g)
|
||||||
|
);
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
Collections.sort(items);
|
blogPosts.setValue(new LiveResult<>(new ListUpdate(null, items)));
|
||||||
blogPosts.setValue(new LiveResult<>(items));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBlogRemoved(GroupId g) {
|
|
||||||
removeAndUpdateListItems(blogPosts, item ->
|
|
||||||
item.getGroupId().equals(g)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public class ContactsViewModel extends DbViewModel implements EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void loadContacts() {
|
protected void loadContacts() {
|
||||||
loadList(this::loadContacts, contactListItems::setValue);
|
loadFromDb(this::loadContacts, contactListItems::setValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ContactListItem> loadContacts(Transaction txn)
|
private List<ContactListItem> loadContacts(Transaction txn)
|
||||||
@@ -151,7 +151,7 @@ public class ContactsViewModel extends DbViewModel implements EventListener {
|
|||||||
@UiThread
|
@UiThread
|
||||||
private void updateItem(ContactId c,
|
private void updateItem(ContactId c,
|
||||||
Function<ContactListItem, ContactListItem> replacer, boolean sort) {
|
Function<ContactListItem, ContactListItem> replacer, boolean sort) {
|
||||||
List<ContactListItem> list = updateListItems(contactListItems,
|
List<ContactListItem> list = updateListItems(getList(contactListItems),
|
||||||
itemToTest -> itemToTest.getContact().getId().equals(c),
|
itemToTest -> itemToTest.getContact().getId().equals(c),
|
||||||
replacer);
|
replacer);
|
||||||
if (list == null) return;
|
if (list == null) return;
|
||||||
@@ -161,10 +161,8 @@ public class ContactsViewModel extends DbViewModel implements EventListener {
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void removeItem(ContactId c) {
|
private void removeItem(ContactId c) {
|
||||||
List<ContactListItem> list = removeListItems(contactListItems,
|
removeAndUpdateListItems(contactListItems,
|
||||||
itemToTest -> itemToTest.getContact().getId().equals(c));
|
itemToTest -> itemToTest.getContact().getId().equals(c));
|
||||||
if (list == null) return;
|
|
||||||
contactListItems.setValue(new LiveResult<>(list));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class ForumListViewModel extends DbViewModel implements EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadForums() {
|
public void loadForums() {
|
||||||
loadList(this::loadForums, forumItems::setValue);
|
loadFromDb(this::loadForums, forumItems::setValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -145,7 +145,7 @@ class ForumListViewModel extends DbViewModel implements EventListener {
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void onForumPostReceived(GroupId g, ForumPostHeader header) {
|
private void onForumPostReceived(GroupId g, ForumPostHeader header) {
|
||||||
List<ForumListItem> list = updateListItems(forumItems,
|
List<ForumListItem> list = updateListItems(getList(forumItems),
|
||||||
itemToTest -> itemToTest.getForum().getId().equals(g),
|
itemToTest -> itemToTest.getForum().getId().equals(g),
|
||||||
itemToUpdate -> new ForumListItem(itemToUpdate, header));
|
itemToUpdate -> new ForumListItem(itemToUpdate, header));
|
||||||
if (list == null) return;
|
if (list == null) return;
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class ForumViewModel extends ThreadListViewModel<ForumPostItem> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadItems() {
|
public void loadItems() {
|
||||||
loadList(txn -> {
|
loadFromDb(txn -> {
|
||||||
long start = now();
|
long start = now();
|
||||||
List<ForumPostHeader> headers =
|
List<ForumPostHeader> headers =
|
||||||
forumManager.getPostHeaders(txn, groupId);
|
forumManager.getPostHeaders(txn, groupId);
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class GroupViewModel extends ThreadListViewModel<GroupMessageItem> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadItems() {
|
public void loadItems() {
|
||||||
loadList(txn -> {
|
loadFromDb(txn -> {
|
||||||
// check first if group is dissolved
|
// check first if group is dissolved
|
||||||
isDissolved
|
isDissolved
|
||||||
.postValue(privateGroupManager.isDissolved(txn, groupId));
|
.postValue(privateGroupManager.isDissolved(txn, groupId));
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.briarproject.briar.android.privategroup.list;
|
|||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
@@ -142,7 +141,7 @@ class GroupListViewModel extends DbViewModel implements EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loadGroups() {
|
void loadGroups() {
|
||||||
loadList(this::loadGroups, groupItems::setValue);
|
loadFromDb(this::loadGroups, groupItems::setValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -173,7 +172,7 @@ class GroupListViewModel extends DbViewModel implements EventListener {
|
|||||||
@UiThread
|
@UiThread
|
||||||
private void onGroupMessageAdded(GroupMessageHeader header) {
|
private void onGroupMessageAdded(GroupMessageHeader header) {
|
||||||
GroupId g = header.getGroupId();
|
GroupId g = header.getGroupId();
|
||||||
List<GroupItem> list = updateListItems(groupItems,
|
List<GroupItem> list = updateListItems(getList(groupItems),
|
||||||
itemToTest -> itemToTest.getId().equals(g),
|
itemToTest -> itemToTest.getId().equals(g),
|
||||||
itemToUpdate -> new GroupItem(itemToUpdate, header));
|
itemToUpdate -> new GroupItem(itemToUpdate, header));
|
||||||
if (list == null) return;
|
if (list == null) return;
|
||||||
@@ -184,7 +183,7 @@ class GroupListViewModel extends DbViewModel implements EventListener {
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void onGroupDissolved(GroupId groupId) {
|
private void onGroupDissolved(GroupId groupId) {
|
||||||
List<GroupItem> list = updateListItems(groupItems,
|
List<GroupItem> list = updateListItems(getList(groupItems),
|
||||||
itemToTest -> itemToTest.getId().equals(groupId),
|
itemToTest -> itemToTest.getId().equals(groupId),
|
||||||
itemToUpdate -> new GroupItem(itemToUpdate, true));
|
itemToUpdate -> new GroupItem(itemToUpdate, true));
|
||||||
if (list == null) return;
|
if (list == null) return;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public abstract class DbViewModel extends AndroidViewModel {
|
|||||||
* <p>
|
* <p>
|
||||||
* If you need a list of items to be displayed in a
|
* If you need a list of items to be displayed in a
|
||||||
* {@link RecyclerView.Adapter},
|
* {@link RecyclerView.Adapter},
|
||||||
* use {@link #loadList(DbCallable, UiConsumer)} instead.
|
* use {@link #loadFromDb(DbCallable, UiConsumer)} instead.
|
||||||
*/
|
*/
|
||||||
protected void runOnDbThread(Runnable task) {
|
protected void runOnDbThread(Runnable task) {
|
||||||
dbExecutor.execute(() -> {
|
dbExecutor.execute(() -> {
|
||||||
@@ -90,7 +90,7 @@ public abstract class DbViewModel extends AndroidViewModel {
|
|||||||
* <p>
|
* <p>
|
||||||
* If you need a list of items to be displayed in a
|
* If you need a list of items to be displayed in a
|
||||||
* {@link RecyclerView.Adapter},
|
* {@link RecyclerView.Adapter},
|
||||||
* use {@link #loadList(DbCallable, UiConsumer)} instead.
|
* use {@link #loadFromDb(DbCallable, UiConsumer)} instead.
|
||||||
*/
|
*/
|
||||||
protected void runOnDbThread(boolean readOnly,
|
protected void runOnDbThread(boolean readOnly,
|
||||||
DbRunnable<Exception> task, Consumer<Exception> err) {
|
DbRunnable<Exception> task, Consumer<Exception> err) {
|
||||||
@@ -108,21 +108,20 @@ public abstract class DbViewModel extends AndroidViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a list of items on the {@link DatabaseExecutor} within a single
|
* Loads a data on the {@link DatabaseExecutor} within a single
|
||||||
* {@link Transaction} and publishes it as a {@link LiveResult}
|
* {@link Transaction} and publishes it as a {@link LiveResult}
|
||||||
* to the {@link UiThread}.
|
* to the {@link UiThread}.
|
||||||
* <p>
|
* <p>
|
||||||
* Use this to ensure that modifications to your local list do not get
|
* Use this to ensure that modifications to your local UI data do not get
|
||||||
* overridden by database loads that were in progress while the modification
|
* overridden by database loads that were in progress while the modification
|
||||||
* was made.
|
* was made.
|
||||||
* E.g. An event about the removal of a message causes the message item to
|
* E.g. An event about the removal of a message causes the message item to
|
||||||
* be removed from the local list while all messages are reloaded.
|
* be removed from the local data set while all messages are reloaded.
|
||||||
* This method ensures that those operations can be processed on the
|
* This method ensures that those operations can be processed on the
|
||||||
* UiThread in the correct order so that the removed message will not be
|
* UiThread in the correct order so that the removed message will not be
|
||||||
* re-added when the re-load completes.
|
* re-added when the re-load completes.
|
||||||
*/
|
*/
|
||||||
protected <T extends List<?>> void loadList(
|
protected <T> void loadFromDb(DbCallable<T, DbException> task,
|
||||||
DbCallable<T, DbException> task,
|
|
||||||
UiConsumer<LiveResult<T>> uiConsumer) {
|
UiConsumer<LiveResult<T>> uiConsumer) {
|
||||||
dbExecutor.execute(() -> {
|
dbExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
@@ -149,63 +148,46 @@ public abstract class DbViewModel extends AndroidViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a copy of the list available in the given LiveData
|
* Creates a copy of the given list and adds the given item to the copy.
|
||||||
* and adds the given item to the copy.
|
|
||||||
*
|
*
|
||||||
* @return a copy of the list in the LiveData with item added or null when
|
* @return an updated copy of the list, or null if the list is null
|
||||||
* <ul>
|
|
||||||
* <li> LiveData does not have a value
|
|
||||||
* <li> LiveResult in the LiveData has an error
|
|
||||||
* </ul>
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected <T> List<T> addListItem(LiveData<LiveResult<List<T>>> liveData,
|
protected <T> List<T> addListItem(@Nullable List<T> list, T item) {
|
||||||
T item) {
|
if (list == null) return null;
|
||||||
List<T> items = getListCopy(liveData);
|
List<T> copy = new ArrayList<>(list);
|
||||||
if (items == null) return null;
|
copy.add(item);
|
||||||
items.add(item);
|
return copy;
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a copy of the list available in the given LiveData
|
* Creates a copy of the given list and adds the given items to the copy.
|
||||||
* and adds the given items to the copy.
|
|
||||||
*
|
*
|
||||||
* @return a copy of the list in the LiveData with items added or null when
|
* @return an updated copy of the list, or null if the list is null
|
||||||
* <ul>
|
|
||||||
* <li> LiveData does not have a value
|
|
||||||
* <li> LiveResult in the LiveData has an error
|
|
||||||
* </ul>
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected <T> List<T> addListItems(LiveData<LiveResult<List<T>>> liveData,
|
protected <T> List<T> addListItems(@Nullable List<T> list,
|
||||||
Collection<T> items) {
|
Collection<T> items) {
|
||||||
List<T> copiedItems = getListCopy(liveData);
|
if (list == null) return null;
|
||||||
if (copiedItems == null) return null;
|
List<T> copy = new ArrayList<>(list);
|
||||||
copiedItems.addAll(items);
|
copy.addAll(items);
|
||||||
return copiedItems;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a copy of the list available in the given LiveData
|
* Creates a copy of the given list, replacing items where the given test
|
||||||
* and replaces items where the given test function returns true.
|
* function returns true.
|
||||||
*
|
*
|
||||||
* @return a copy of the list in the LiveData with item(s) replaced
|
* @return an updated copy of the list, or null if either the list is null
|
||||||
* or null when the
|
* or the test function returns false for all items
|
||||||
* <ul>
|
|
||||||
* <li> LiveData does not have a value
|
|
||||||
* <li> LiveResult in the LiveData has an error
|
|
||||||
* <li> test function did return false for all items in the list
|
|
||||||
* </ul>
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected <T> List<T> updateListItems(
|
protected <T> List<T> updateListItems(@Nullable List<T> list,
|
||||||
LiveData<LiveResult<List<T>>> liveData, Function<T, Boolean> test,
|
Function<T, Boolean> test, Function<T, T> replacer) {
|
||||||
Function<T, T> replacer) {
|
if (list == null) return null;
|
||||||
List<T> items = getListCopy(liveData);
|
List<T> copy = new ArrayList<>(list);
|
||||||
if (items == null) return null;
|
|
||||||
|
|
||||||
ListIterator<T> iterator = items.listIterator();
|
ListIterator<T> iterator = copy.listIterator();
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
T item = iterator.next();
|
T item = iterator.next();
|
||||||
@@ -214,28 +196,23 @@ public abstract class DbViewModel extends AndroidViewModel {
|
|||||||
iterator.set(replacer.apply(item));
|
iterator.set(replacer.apply(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return changed ? items : null;
|
return changed ? copy : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a copy of the list available in the given LiveData
|
* Creates a copy of the given list, removing items from it where the given
|
||||||
* and removes the items from it where the given test function returns true.
|
* test function returns true.
|
||||||
*
|
*
|
||||||
* @return a copy of the list in the LiveData with item(s) removed
|
* @return an updated copy of the list, or null if either the list is null
|
||||||
* or null when the
|
* or the test function returns false for all items
|
||||||
* <ul>
|
|
||||||
* <li> LiveData does not have a value
|
|
||||||
* <li> LiveResult in the LiveData has an error
|
|
||||||
* <li> test function did return false for all items in the list
|
|
||||||
* </ul>
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected <T> List<T> removeListItems(
|
protected <T> List<T> removeListItems(@Nullable List<T> list,
|
||||||
LiveData<LiveResult<List<T>>> liveData, Function<T, Boolean> test) {
|
Function<T, Boolean> test) {
|
||||||
List<T> items = getListCopy(liveData);
|
if (list == null) return null;
|
||||||
if (items == null) return null;
|
List<T> copy = new ArrayList<>(list);
|
||||||
|
|
||||||
ListIterator<T> iterator = items.listIterator();
|
ListIterator<T> iterator = copy.listIterator();
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
T item = iterator.next();
|
T item = iterator.next();
|
||||||
@@ -244,7 +221,7 @@ public abstract class DbViewModel extends AndroidViewModel {
|
|||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return changed ? items : null;
|
return changed ? copy : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,29 +232,26 @@ public abstract class DbViewModel extends AndroidViewModel {
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li> LiveData does not have a value
|
* <li> LiveData does not have a value
|
||||||
* <li> LiveResult in the LiveData has an error
|
* <li> LiveResult in the LiveData has an error
|
||||||
* <li> test function did return false for all items in the list
|
* <li> test function returned false for all items in the list
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@UiThread
|
@UiThread
|
||||||
protected <T> void removeAndUpdateListItems(
|
protected <T> void removeAndUpdateListItems(
|
||||||
MutableLiveData<LiveResult<List<T>>> liveData,
|
MutableLiveData<LiveResult<List<T>>> liveData,
|
||||||
Function<T, Boolean> test) {
|
Function<T, Boolean> test) {
|
||||||
List<T> list = removeListItems(liveData, test);
|
List<T> copy = removeListItems(getList(liveData), test);
|
||||||
if (list != null) liveData.setValue(new LiveResult<>(list));
|
if (copy != null) liveData.setValue(new LiveResult<>(copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a copy of the list of items from the given LiveData
|
* Returns the list of items from the given LiveData, or null if no list is
|
||||||
* or null if it is not available.
|
* available.
|
||||||
* The list copy can be safely mutated.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private <T> List<T> getListCopy(LiveData<LiveResult<List<T>>> liveData) {
|
protected <T> List<T> getList(LiveData<LiveResult<List<T>>> liveData) {
|
||||||
LiveResult<List<T>> value = liveData.getValue();
|
LiveResult<List<T>> value = liveData.getValue();
|
||||||
if (value == null) return null;
|
if (value == null) return null;
|
||||||
List<T> list = value.getResultOrNull();
|
return value.getResultOrNull();
|
||||||
if (list == null) return null;
|
|
||||||
return new ArrayList<>(list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user