mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Add transactional helper methods to DbViewModel.
This commit is contained in:
@@ -2,12 +2,9 @@ package org.briarproject.briar.android.contact.add.remote;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.contact.PendingContact;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.NoSuchPendingContactException;
|
||||
import org.briarproject.bramble.api.db.TransactionManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
@@ -18,7 +15,6 @@ import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||
import org.briarproject.briar.android.viewmodel.LiveResult;
|
||||
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -101,17 +97,11 @@ public class AddContactViewModel extends DbViewModel {
|
||||
void addContact(String nickname) {
|
||||
if (remoteHandshakeLink == null) throw new IllegalStateException();
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
contactManager.addPendingContact(remoteHandshakeLink, nickname);
|
||||
addContactResult.postValue(new LiveResult<>(true));
|
||||
} catch (UnsupportedVersionException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
addContactResult.postValue(new LiveResult<>(e));
|
||||
} catch (DbException | FormatException
|
||||
| GeneralSecurityException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
addContactResult.postValue(new LiveResult<>(e));
|
||||
}
|
||||
contactManager.addPendingContact(remoteHandshakeLink, nickname);
|
||||
addContactResult.postValue(new LiveResult<>(true));
|
||||
}, e -> {
|
||||
logException(LOG, WARNING, e);
|
||||
addContactResult.postValue(new LiveResult<>(e));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,13 +111,13 @@ public class AddContactViewModel extends DbViewModel {
|
||||
|
||||
public void updatePendingContact(String name, PendingContact p) {
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
contactManager.removePendingContact(p.getId());
|
||||
addContact(name);
|
||||
} catch (NoSuchPendingContactException e) {
|
||||
contactManager.removePendingContact(p.getId());
|
||||
addContact(name);
|
||||
}, e -> {
|
||||
if (e instanceof NoSuchPendingContactException) {
|
||||
logException(LOG, WARNING, e);
|
||||
// no error in UI as pending contact was converted into contact
|
||||
} catch (DbException e) {
|
||||
} else {
|
||||
logException(LOG, WARNING, e);
|
||||
addContactResult.postValue(new LiveResult<>(e));
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class ConversationViewModel extends DbViewModel
|
||||
AttachmentReceivedEvent a = (AttachmentReceivedEvent) e;
|
||||
if (a.getContactId().equals(contactId)) {
|
||||
LOG.info("Attachment received");
|
||||
runOnDbThread(() -> attachmentRetriever
|
||||
runOnDbThreadOrLogException(() -> attachmentRetriever
|
||||
.loadAttachmentItem(a.getMessageId()));
|
||||
}
|
||||
} else if (e instanceof AvatarUpdatedEvent) {
|
||||
@@ -194,18 +194,18 @@ public class ConversationViewModel extends DbViewModel
|
||||
|
||||
private void loadContact(ContactId contactId) {
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long start = now();
|
||||
Contact c = contactManager.getContact(contactId);
|
||||
AuthorInfo authorInfo = authorManager.getAuthorInfo(c);
|
||||
contactItem.postValue(new ContactItem(c, authorInfo));
|
||||
logDuration(LOG, "Loading contact", start);
|
||||
start = now();
|
||||
checkFeaturesAndOnboarding(contactId);
|
||||
logDuration(LOG, "Checking for image support", start);
|
||||
} catch (NoSuchContactException e) {
|
||||
long start = now();
|
||||
Contact c = contactManager.getContact(contactId);
|
||||
AuthorInfo authorInfo = authorManager.getAuthorInfo(c);
|
||||
contactItem.postValue(new ContactItem(c, authorInfo));
|
||||
logDuration(LOG, "Loading contact", start);
|
||||
start = now();
|
||||
checkFeaturesAndOnboarding(contactId);
|
||||
logDuration(LOG, "Checking for image support", start);
|
||||
}, e -> {
|
||||
if (e instanceof NoSuchContactException) {
|
||||
contactDeleted.postValue(true);
|
||||
} catch (DbException e) {
|
||||
} else {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.net.Uri;
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.TransactionManager;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
@@ -198,14 +197,12 @@ public class ImageViewModel extends DbViewModel implements EventListener {
|
||||
private void saveImage(AttachmentItem attachment, OutputStreamProvider osp,
|
||||
@Nullable Runnable afterCopy) {
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Attachment a =
|
||||
attachmentReader.getAttachment(attachment.getHeader());
|
||||
copyImageFromDb(a, osp, afterCopy);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
saveState.postEvent(true);
|
||||
}
|
||||
Attachment a =
|
||||
attachmentReader.getAttachment(attachment.getHeader());
|
||||
copyImageFromDb(a, osp, afterCopy);
|
||||
}, e -> {
|
||||
logException(LOG, WARNING, e);
|
||||
saveState.postEvent(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -184,12 +184,12 @@ class ForumViewModel extends ThreadListViewModel<ForumPostItem> {
|
||||
}
|
||||
|
||||
public void loadSharingContacts() {
|
||||
runOnDbThreadOrLogException(() -> {
|
||||
runOnDbThreadOrLogException(true, txn -> {
|
||||
Collection<Contact> contacts =
|
||||
forumSharingManager.getSharedWith(groupId);
|
||||
forumSharingManager.getSharedWith(txn, groupId);
|
||||
Collection<ContactId> contactIds = new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) contactIds.add(c.getId());
|
||||
sharingController.addAll(contactIds);
|
||||
txn.attach(() -> sharingController.addAll(contactIds));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.briarproject.briar.android.navdrawer;
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.TransactionManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -114,15 +113,12 @@ public class NavDrawerViewModel extends DbViewModel {
|
||||
return;
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Settings settings =
|
||||
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true);
|
||||
shouldAskForDozeWhitelisting.postValue(ask);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
shouldAskForDozeWhitelisting.postValue(true);
|
||||
}
|
||||
Settings settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true);
|
||||
shouldAskForDozeWhitelisting.postValue(ask);
|
||||
}, e -> {
|
||||
logException(LOG, WARNING, e);
|
||||
shouldAskForDozeWhitelisting.postValue(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -223,14 +223,14 @@ class GroupViewModel extends ThreadListViewModel<GroupMessageItem> {
|
||||
}
|
||||
|
||||
public void loadSharingContacts() {
|
||||
runOnDbThreadOrLogException(() -> {
|
||||
runOnDbThreadOrLogException(true, txn -> {
|
||||
Collection<GroupMember> members =
|
||||
privateGroupManager.getMembers(groupId);
|
||||
privateGroupManager.getMembers(txn, groupId);
|
||||
Collection<ContactId> contactIds = new ArrayList<>();
|
||||
for (GroupMember m : members) {
|
||||
if (m.getContactId() != null) contactIds.add(m.getContactId());
|
||||
}
|
||||
sharingController.addAll(contactIds);
|
||||
txn.attach(() -> sharingController.addAll(contactIds));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.briarproject.briar.android.sharing;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@@ -28,7 +27,7 @@ public interface SharingController {
|
||||
/**
|
||||
* Adds a collection of contacts to be tracked.
|
||||
*/
|
||||
@DatabaseExecutor
|
||||
@UiThread
|
||||
void addAll(Collection<ContactId> contacts);
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,14 +2,12 @@ package org.briarproject.briar.android.sharing;
|
||||
|
||||
import org.briarproject.bramble.api.connection.ConnectionRegistry;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
|
||||
import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -26,7 +24,6 @@ public class SharingControllerImpl implements SharingController, EventListener {
|
||||
|
||||
private final EventBus eventBus;
|
||||
private final ConnectionRegistry connectionRegistry;
|
||||
private final AndroidExecutor executor;
|
||||
|
||||
// UI thread
|
||||
private final Set<ContactId> contacts = new HashSet<>();
|
||||
@@ -35,11 +32,9 @@ public class SharingControllerImpl implements SharingController, EventListener {
|
||||
|
||||
@Inject
|
||||
SharingControllerImpl(EventBus eventBus,
|
||||
ConnectionRegistry connectionRegistry,
|
||||
AndroidExecutor executor) {
|
||||
ConnectionRegistry connectionRegistry) {
|
||||
this.eventBus = eventBus;
|
||||
this.connectionRegistry = connectionRegistry;
|
||||
this.executor = executor;
|
||||
eventBus.addListener(this);
|
||||
}
|
||||
|
||||
@@ -78,13 +73,11 @@ public class SharingControllerImpl implements SharingController, EventListener {
|
||||
return online;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
@DatabaseExecutor
|
||||
public void addAll(Collection<ContactId> c) {
|
||||
executor.runOnUiThread(() -> {
|
||||
contacts.addAll(c);
|
||||
updateLiveData();
|
||||
});
|
||||
contacts.addAll(c);
|
||||
updateLiveData();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.ThrowingRunnable;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbCallable;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.DbRunnable;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.db.TransactionManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
@@ -24,6 +25,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.arch.core.util.Function;
|
||||
import androidx.core.util.Consumer;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
@@ -58,14 +60,15 @@ public abstract class DbViewModel extends AndroidViewModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given task on the {@link DatabaseExecutor}
|
||||
* and waits for the DB to open.
|
||||
* Waits for the DB to open and runs the given task on the
|
||||
* {@link DatabaseExecutor}.
|
||||
* <p>
|
||||
* If you need a list of items to be displayed in a
|
||||
* {@link RecyclerView.Adapter},
|
||||
* use {@link #loadList(DbCallable, UiConsumer)} instead.
|
||||
*/
|
||||
protected void runOnDbThread(Runnable task) {
|
||||
protected void runOnDbThread(ThrowingRunnable<Exception> task,
|
||||
Consumer<Exception> err) {
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
lifecycleManager.waitForDatabase();
|
||||
@@ -73,13 +76,52 @@ public abstract class DbViewModel extends AndroidViewModel {
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while waiting for database");
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception e) {
|
||||
err.accept(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given task on the {@link DatabaseExecutor}
|
||||
* and waits for the DB to open. If the task throws a {@link DbException}
|
||||
* Waits for the DB to open and runs the given task on the
|
||||
* {@link DatabaseExecutor}.
|
||||
* <p>
|
||||
* If you need a list of items to be displayed in a
|
||||
* {@link RecyclerView.Adapter},
|
||||
* use {@link #loadList(DbCallable, UiConsumer)} instead.
|
||||
*/
|
||||
protected void runOnDbThread(boolean readOnly,
|
||||
DbRunnable<Exception> task, Consumer<Exception> err) {
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
lifecycleManager.waitForDatabase();
|
||||
db.transaction(readOnly, task);
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while waiting for database");
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception e) {
|
||||
err.accept(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the DB to open and runs the given task on the
|
||||
* {@link DatabaseExecutor}. If the task throws a {@link DbException}
|
||||
* it's caught and logged.
|
||||
* <p>
|
||||
* If you need a list of items to be displayed in a
|
||||
* {@link RecyclerView.Adapter},
|
||||
* use {@link #loadList(DbCallable, UiConsumer)} instead.
|
||||
*/
|
||||
protected void runOnDbThreadOrLogException(boolean readOnly,
|
||||
DbRunnable<Exception> task) {
|
||||
runOnDbThread(readOnly, task, e -> logException(LOG, WARNING, e));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the DB to open and runs the given task on the
|
||||
* {@link DatabaseExecutor}. If the task throws a {@link DbException}
|
||||
* it's caught and logged.
|
||||
* <p>
|
||||
* If you need a list of items to be displayed in a
|
||||
@@ -87,18 +129,8 @@ public abstract class DbViewModel extends AndroidViewModel {
|
||||
* use {@link #loadList(DbCallable, UiConsumer)} instead.
|
||||
*/
|
||||
protected void runOnDbThreadOrLogException(
|
||||
ThrowingRunnable<DbException> task) {
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
lifecycleManager.waitForDatabase();
|
||||
task.run();
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while waiting for database");
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
});
|
||||
ThrowingRunnable<Exception> task) {
|
||||
runOnDbThread(task, e -> logException(LOG, WARNING, e));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user