From 9d9bc4ca84dd02cfa18c7450a99049fa17ff8cad Mon Sep 17 00:00:00 2001 From: Torsten Grote <t@grobox.de> Date: Sun, 14 Apr 2019 12:31:31 -0300 Subject: [PATCH] [android] Let AttachmentCreator return same LiveData after configuration changes --- .../android/attachment/AttachmentCreator.java | 57 +++++++++++-------- .../android/attachment/AttachmentManager.java | 2 +- .../conversation/ConversationViewModel.java | 8 +-- .../view/TextAttachmentController.java | 11 ++-- 4 files changed, 43 insertions(+), 35 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreator.java b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreator.java index e03a0d7b56..ea8341de6f 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreator.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreator.java @@ -29,7 +29,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.logging.Logger; -import static java.util.Objects.requireNonNull; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.LogUtils.logException; @@ -46,6 +45,7 @@ public class AttachmentCreator { private final MessagingManager messagingManager; private final AttachmentRetriever retriever; + // store unsent items separately, as LiveData might not return latest value private final Map<Uri, AttachmentItem> unsentItems = new ConcurrentHashMap<>(); private final Map<Uri, MutableLiveData<AttachmentItemResult>> @@ -66,32 +66,38 @@ public class AttachmentCreator { @UiThread public AttachmentResult storeAttachments(GroupId groupId, - Collection<Uri> uris) { - if (task != null && !isStoring()) throw new AssertionError(); + Collection<Uri> uris, boolean restart) { List<LiveData<AttachmentItemResult>> itemResults = new ArrayList<>(); - List<Uri> urisToStore = new ArrayList<>(); - for (Uri uri : uris) { - MutableLiveData<AttachmentItemResult> liveData = - new MutableLiveData<>(); - itemResults.add(liveData); - liveDataResult.put(uri, liveData); - if (unsentItems.containsKey(uri)) { - // This can happen due to configuration changes. - // So don't create a new attachment, if we have one already. - AttachmentItem item = requireNonNull(unsentItems.get(uri)); - AttachmentItemResult result = - new AttachmentItemResult(uri, item); - liveData.setValue(result); - } else { + if (restart) { + // This can happen due to configuration changes. + // So don't create new attachments, if we have (or creating) them. + // Instead, re-subscribe to the existing LiveData. + if (task == null || isNotStoring()) throw new AssertionError(); + for (Uri uri : uris) { + // We don't want to expose mutable(!) LiveData + LiveData<AttachmentItemResult> liveData = + liveDataResult.get(uri); + if (liveData == null) throw new IllegalStateException(); + itemResults.add(liveData); + } + if (liveDataFinished == null) throw new IllegalStateException(); + } else { + if (task != null && isNotStoring()) throw new AssertionError(); + List<Uri> urisToStore = new ArrayList<>(); + for (Uri uri : uris) { urisToStore.add(uri); + MutableLiveData<AttachmentItemResult> liveData = + new MutableLiveData<>(); + liveDataResult.put(uri, liveData); + itemResults.add(liveData); } + boolean needsSize = uris.size() == 1; + task = new AttachmentCreationTask(messagingManager, + app.getContentResolver(), this, groupId, urisToStore, + needsSize); + ioExecutor.execute(() -> task.storeAttachments()); + liveDataFinished = new MutableLiveData<>(); } - boolean needsSize = uris.size() == 1; - task = new AttachmentCreationTask(messagingManager, - app.getContentResolver(), this, groupId, urisToStore, - needsSize); - ioExecutor.execute(() -> task.storeAttachments()); - liveDataFinished = new MutableLiveData<>(); return new AttachmentResult(itemResults, liveDataFinished); } @@ -185,6 +191,7 @@ public class AttachmentCreator { @UiThread public void deleteUnsentAttachments() { + // Make a copy for the IoExecutor as we clear the unsentItems soon List<AttachmentItem> itemsToDelete = new ArrayList<>(unsentItems.values()); ioExecutor.execute(() -> { @@ -198,8 +205,8 @@ public class AttachmentCreator { }); } - private boolean isStoring() { - return liveDataFinished != null; + private boolean isNotStoring() { + return liveDataFinished == null; } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentManager.java b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentManager.java index 194af99ec1..f478b2c53d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentManager.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentManager.java @@ -11,7 +11,7 @@ import java.util.List; @UiThread public interface AttachmentManager { - AttachmentResult storeAttachments(Collection<Uri> uri); + AttachmentResult storeAttachments(Collection<Uri> uri, boolean restart); List<AttachmentHeader> getAttachmentHeadersForSending(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java index aa8718c0f3..40b21f0f73 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java @@ -150,8 +150,7 @@ public class ConversationViewModel extends AndroidViewModel contact.postValue(c); logDuration(LOG, "Loading contact", start); start = now(); - messagingGroupId = - messagingManager.getConversationId(contactId); + messagingGroupId = messagingManager.getContactGroup(c).getId(); logDuration(LOG, "Load conversation GroupId", start); start = now(); checkFeaturesAndOnboarding(contactId); @@ -197,10 +196,11 @@ public class ConversationViewModel extends AndroidViewModel @Override @UiThread - public AttachmentResult storeAttachments(Collection<Uri> uris) { + public AttachmentResult storeAttachments(Collection<Uri> uris, + boolean restart) { GroupId groupId = messagingGroupId; if (groupId == null) throw new IllegalStateException(); - return attachmentCreator.storeAttachments(groupId, uris); + return attachmentCreator.storeAttachments(groupId, uris, restart); } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java index b7bd4f23f6..5f549a8634 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java @@ -153,17 +153,17 @@ public class TextAttachmentController extends TextSendController if (loadingUris || !imageUris.isEmpty()) throw new AssertionError(); if (resultData.getData() != null) { imageUris.add(resultData.getData()); - onNewUris(); + onNewUris(false); } else if (SDK_INT >= 18 && resultData.getClipData() != null) { ClipData clipData = resultData.getClipData(); for (int i = 0; i < clipData.getItemCount(); i++) { imageUris.add(clipData.getItemAt(i).getUri()); } - onNewUris(); + onNewUris(false); } } - private void onNewUris() { + private void onNewUris(boolean restart) { if (imageUris.isEmpty()) return; if (loadingUris) throw new AssertionError(); loadingUris = true; @@ -172,7 +172,8 @@ public class TextAttachmentController extends TextSendController List<ImagePreviewItem> items = ImagePreviewItem.fromUris(imageUris); imagePreview.showPreview(items); // store attachments and show preview when successful - AttachmentResult result = attachmentManager.storeAttachments(imageUris); + AttachmentResult result = + attachmentManager.storeAttachments(imageUris, restart); for (LiveData<AttachmentItemResult> liveData : result .getItemResults()) { onLiveDataReturned(liveData); @@ -240,7 +241,7 @@ public class TextAttachmentController extends TextSendController SavedState state = (SavedState) inState; if (!imageUris.isEmpty()) throw new AssertionError(); if (state.imageUris != null) imageUris.addAll(state.imageUris); - onNewUris(); + onNewUris(true); return state.getSuperState(); } -- GitLab