From b78dfea95fc1c72712a63c37dda6c43853dea020 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 7 Sep 2018 13:17:56 -0300 Subject: [PATCH] Remove ListenableFutureTask and replace it with LiveData --- .../android/contact/ConversationActivity.java | 120 ++++++++---------- .../components/util/FutureTaskListener.java | 23 ---- .../components/util/ListenableFutureTask.java | 105 --------------- 3 files changed, 55 insertions(+), 193 deletions(-) delete mode 100644 briar-android/src/main/java/org/thoughtcrime/securesms/components/util/FutureTaskListener.java delete mode 100644 briar-android/src/main/java/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java index e1ccf6a57..a086733b0 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java @@ -1,8 +1,11 @@ package org.briarproject.briar.android.contact; +import android.arch.lifecycle.MutableLiveData; +import android.arch.lifecycle.Observer; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.annotation.UiThread; import android.support.design.widget.Snackbar; import android.support.v4.content.ContextCompat; @@ -72,8 +75,6 @@ import org.briarproject.briar.api.messaging.PrivateRequest; import org.briarproject.briar.api.messaging.PrivateResponse; import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; -import org.thoughtcrime.securesms.components.util.FutureTaskListener; -import org.thoughtcrime.securesms.components.util.ListenableFutureTask; import java.util.ArrayList; import java.util.Collection; @@ -81,13 +82,10 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; -import javax.annotation.Nullable; import javax.inject.Inject; import de.hdodenhof.circleimageview.CircleImageView; @@ -141,18 +139,6 @@ public class ConversationActivity extends BriarActivity private BriarRecyclerView list; private TextInputView textInputView; - private final ListenableFutureTask contactNameTask = - new ListenableFutureTask<>(new Callable() { - @Override - public String call() throws Exception { - Contact c = contactManager.getContact(contactId); - contactName = c.getAuthor().getName(); - return c.getAuthor().getName(); - } - }); - private final AtomicBoolean contactNameTaskStarted = - new AtomicBoolean(false); - // Fields that are accessed from background threads must be volatile @Inject volatile ContactManager contactManager; @@ -177,11 +163,10 @@ public class ConversationActivity extends BriarActivity private volatile ContactId contactId; @Nullable - private volatile String contactName; - @Nullable private volatile AuthorId contactAuthorId; @Nullable private volatile GroupId messagingGroupId; + private MutableLiveData contactName = new MutableLiveData<>(); @SuppressWarnings("ConstantConditions") @Override @@ -292,7 +277,7 @@ public class ConversationActivity extends BriarActivity long start = now(); if (contactName == null || contactAuthorId == null) { Contact contact = contactManager.getContact(contactId); - contactName = contact.getAuthor().getName(); + contactName.postValue(contact.getAuthor().getName()); contactAuthorId = contact.getAuthor().getId(); } logDuration(LOG, "Loading contact", start); @@ -306,12 +291,13 @@ public class ConversationActivity extends BriarActivity }); } + // contactAuthorId and contactName are expected to be set private void displayContactDetails() { runOnUiThreadUnlessDestroyed(() -> { //noinspection ConstantConditions toolbarAvatar.setImageDrawable( new IdenticonDrawable(contactAuthorId.getBytes())); - toolbarTitle.setText(contactName); + toolbarTitle.setText(contactName.getValue()); }); } @@ -381,13 +367,13 @@ public class ConversationActivity extends BriarActivity ConversationItem item; if (h instanceof IntroductionResponse) { IntroductionResponse i = (IntroductionResponse) h; - item = ConversationItem.from(this, contactName, i); + item = ConversationItem.from(this, contactName.getValue(), i); } else if (h instanceof PrivateRequest) { PrivateRequest r = (PrivateRequest) h; - item = ConversationItem.from(this, contactName, r); + item = ConversationItem.from(this, contactName.getValue(), r); } else if (h instanceof PrivateResponse) { PrivateResponse r = (PrivateResponse) h; - item = ConversationItem.from(this, contactName, r); + item = ConversationItem.from(this, contactName.getValue(), r); } else { item = ConversationItem.from(h); String body = bodyCache.get(h.getId()); @@ -480,43 +466,42 @@ public class ConversationActivity extends BriarActivity } private void onNewPrivateMessage(PrivateMessageHeader h) { - if (h instanceof PrivateRequest || h instanceof PrivateResponse) { - getContactNameTask().addListener(new FutureTaskListener() { - @Override - public void onSuccess(String contactName) { - runOnUiThreadUnlessDestroyed( - () -> handlePrivateRequestAndResponse(h, - contactName)); - } - - @Override - public void onFailure(Throwable exception) { - runOnUiThreadUnlessDestroyed( - () -> handleDbException((DbException) exception)); - } - }); - } else { - addConversationItem(ConversationItem.from(h)); - loadMessageBody(h.getId()); - } - } - - @UiThread - private void handlePrivateRequestAndResponse(PrivateMessageHeader h, - String contactName) { - ConversationItem item; - if (h instanceof PrivateRequest) { - PrivateRequest m = (PrivateRequest) h; - item = ConversationItem - .from(ConversationActivity.this, contactName, m); - } else if (h instanceof PrivateResponse) { - PrivateResponse m = (PrivateResponse) h; - item = ConversationItem - .from(ConversationActivity.this, contactName, m); - } else { - throw new AssertionError("Unknown PrivateMessageHeader"); - } - addConversationItem(item); + runOnUiThreadUnlessDestroyed(() -> { + if (h instanceof PrivateRequest) { + contactName.observe(this, new Observer() { + @Override + public void onChanged(@Nullable String name) { + if (name == null) loadContactName(); + else { + PrivateRequest m = (PrivateRequest) h; + ConversationItem item = ConversationItem.from( + ConversationActivity.this, name, m); + addConversationItem(item); + contactName.removeObserver(this); + } + } + }); + if (contactName.getValue() == null) loadContactName(); + } else if (h instanceof PrivateResponse) { + contactName.observe(this, new Observer() { + @Override + public void onChanged(@Nullable String name) { + if (name == null) loadContactName(); + else { + PrivateResponse m = (PrivateResponse) h; + ConversationItem item = ConversationItem.from( + ConversationActivity.this, name, m); + addConversationItem(item); + contactName.removeObserver(this); + } + } + }); + if (contactName.getValue() == null) loadContactName(); + } else { + addConversationItem(ConversationItem.from(h)); + loadMessageBody(h.getId()); + } + }); } private void markMessages(Collection messageIds, boolean sent, @@ -804,10 +789,15 @@ public class ConversationActivity extends BriarActivity groupInvitationManager.respondToInvitation(contactId, id, accept); } - private ListenableFutureTask getContactNameTask() { - if (!contactNameTaskStarted.getAndSet(true)) - runOnDbThread(contactNameTask); - return contactNameTask; + private void loadContactName() { + runOnDbThread(() -> { + try { + Contact c = contactManager.getContact(contactId); + contactName.postValue(c.getAuthor().getName()); + } catch (DbException e) { + handleDbException(e); + } + }); } } diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/FutureTaskListener.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/FutureTaskListener.java deleted file mode 100644 index 80da2eccf..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/FutureTaskListener.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (C) 2014 Open Whisper Systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.thoughtcrime.securesms.components.util; - -public interface FutureTaskListener { - void onSuccess(V result); - - void onFailure(Throwable error); -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java deleted file mode 100644 index 3d8303f07..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2014 Open Whisper Systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.thoughtcrime.securesms.components.util; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -import javax.annotation.Nullable; - -public class ListenableFutureTask extends FutureTask { - - private final List> listeners = new LinkedList<>(); - - @Nullable - private final Object identifier; - - public ListenableFutureTask(Callable callable) { - this(callable, null); - } - - private ListenableFutureTask(Callable callable, - @Nullable Object identifier) { - super(callable); - this.identifier = identifier; - } - - public ListenableFutureTask(V result) { - this(result, null); - } - - private ListenableFutureTask(V result, @Nullable Object identifier) { - super(() -> result); - this.identifier = identifier; - this.run(); - } - - public synchronized void addListener(FutureTaskListener listener) { - if (this.isDone()) { - callback(listener); - } else { - this.listeners.add(listener); - } - } - - public synchronized void removeListener(FutureTaskListener listener) { - this.listeners.remove(listener); - } - - @Override - protected synchronized void done() { - callback(); - } - - private void callback() { - for (FutureTaskListener listener : listeners) { - callback(listener); - } - } - - private void callback(FutureTaskListener listener) { - if (listener != null) { - try { - listener.onSuccess(get()); - } catch (InterruptedException e) { - throw new AssertionError(e); - } catch (ExecutionException e) { - listener.onFailure(e); - } - } - } - - @Override - public boolean equals(Object other) { - if (other != null && other instanceof ListenableFutureTask && - this.identifier != null) { - return identifier.equals(other); - } else { - return super.equals(other); - } - } - - @Override - public int hashCode() { - if (identifier != null) return identifier.hashCode(); - else return super.hashCode(); - } - -}