mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 15:19:53 +01:00
Remove ListenableFutureTask and replace it with LiveData
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
package org.briarproject.briar.android.contact;
|
package org.briarproject.briar.android.contact;
|
||||||
|
|
||||||
|
import android.arch.lifecycle.MutableLiveData;
|
||||||
|
import android.arch.lifecycle.Observer;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.content.ContextCompat;
|
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.PrivateResponse;
|
||||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
|
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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -81,13 +82,10 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
import de.hdodenhof.circleimageview.CircleImageView;
|
||||||
@@ -141,18 +139,6 @@ public class ConversationActivity extends BriarActivity
|
|||||||
private BriarRecyclerView list;
|
private BriarRecyclerView list;
|
||||||
private TextInputView textInputView;
|
private TextInputView textInputView;
|
||||||
|
|
||||||
private final ListenableFutureTask<String> contactNameTask =
|
|
||||||
new ListenableFutureTask<>(new Callable<String>() {
|
|
||||||
@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
|
// Fields that are accessed from background threads must be volatile
|
||||||
@Inject
|
@Inject
|
||||||
volatile ContactManager contactManager;
|
volatile ContactManager contactManager;
|
||||||
@@ -177,11 +163,10 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
private volatile ContactId contactId;
|
private volatile ContactId contactId;
|
||||||
@Nullable
|
@Nullable
|
||||||
private volatile String contactName;
|
|
||||||
@Nullable
|
|
||||||
private volatile AuthorId contactAuthorId;
|
private volatile AuthorId contactAuthorId;
|
||||||
@Nullable
|
@Nullable
|
||||||
private volatile GroupId messagingGroupId;
|
private volatile GroupId messagingGroupId;
|
||||||
|
private MutableLiveData<String> contactName = new MutableLiveData<>();
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
@Override
|
@Override
|
||||||
@@ -292,7 +277,7 @@ public class ConversationActivity extends BriarActivity
|
|||||||
long start = now();
|
long start = now();
|
||||||
if (contactName == null || contactAuthorId == null) {
|
if (contactName == null || contactAuthorId == null) {
|
||||||
Contact contact = contactManager.getContact(contactId);
|
Contact contact = contactManager.getContact(contactId);
|
||||||
contactName = contact.getAuthor().getName();
|
contactName.postValue(contact.getAuthor().getName());
|
||||||
contactAuthorId = contact.getAuthor().getId();
|
contactAuthorId = contact.getAuthor().getId();
|
||||||
}
|
}
|
||||||
logDuration(LOG, "Loading contact", start);
|
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() {
|
private void displayContactDetails() {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
toolbarAvatar.setImageDrawable(
|
toolbarAvatar.setImageDrawable(
|
||||||
new IdenticonDrawable(contactAuthorId.getBytes()));
|
new IdenticonDrawable(contactAuthorId.getBytes()));
|
||||||
toolbarTitle.setText(contactName);
|
toolbarTitle.setText(contactName.getValue());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,13 +367,13 @@ public class ConversationActivity extends BriarActivity
|
|||||||
ConversationItem item;
|
ConversationItem item;
|
||||||
if (h instanceof IntroductionResponse) {
|
if (h instanceof IntroductionResponse) {
|
||||||
IntroductionResponse i = (IntroductionResponse) h;
|
IntroductionResponse i = (IntroductionResponse) h;
|
||||||
item = ConversationItem.from(this, contactName, i);
|
item = ConversationItem.from(this, contactName.getValue(), i);
|
||||||
} else if (h instanceof PrivateRequest) {
|
} else if (h instanceof PrivateRequest) {
|
||||||
PrivateRequest r = (PrivateRequest) h;
|
PrivateRequest r = (PrivateRequest) h;
|
||||||
item = ConversationItem.from(this, contactName, r);
|
item = ConversationItem.from(this, contactName.getValue(), r);
|
||||||
} else if (h instanceof PrivateResponse) {
|
} else if (h instanceof PrivateResponse) {
|
||||||
PrivateResponse r = (PrivateResponse) h;
|
PrivateResponse r = (PrivateResponse) h;
|
||||||
item = ConversationItem.from(this, contactName, r);
|
item = ConversationItem.from(this, contactName.getValue(), r);
|
||||||
} else {
|
} else {
|
||||||
item = ConversationItem.from(h);
|
item = ConversationItem.from(h);
|
||||||
String body = bodyCache.get(h.getId());
|
String body = bodyCache.get(h.getId());
|
||||||
@@ -480,43 +466,42 @@ public class ConversationActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onNewPrivateMessage(PrivateMessageHeader h) {
|
private void onNewPrivateMessage(PrivateMessageHeader h) {
|
||||||
if (h instanceof PrivateRequest || h instanceof PrivateResponse) {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
if (h instanceof PrivateRequest) {
|
||||||
@Override
|
contactName.observe(this, new Observer<String>() {
|
||||||
public void onSuccess(String contactName) {
|
@Override
|
||||||
runOnUiThreadUnlessDestroyed(
|
public void onChanged(@Nullable String name) {
|
||||||
() -> handlePrivateRequestAndResponse(h,
|
if (name == null) loadContactName();
|
||||||
contactName));
|
else {
|
||||||
}
|
PrivateRequest m = (PrivateRequest) h;
|
||||||
|
ConversationItem item = ConversationItem.from(
|
||||||
@Override
|
ConversationActivity.this, name, m);
|
||||||
public void onFailure(Throwable exception) {
|
addConversationItem(item);
|
||||||
runOnUiThreadUnlessDestroyed(
|
contactName.removeObserver(this);
|
||||||
() -> handleDbException((DbException) exception));
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
if (contactName.getValue() == null) loadContactName();
|
||||||
addConversationItem(ConversationItem.from(h));
|
} else if (h instanceof PrivateResponse) {
|
||||||
loadMessageBody(h.getId());
|
contactName.observe(this, new Observer<String>() {
|
||||||
}
|
@Override
|
||||||
}
|
public void onChanged(@Nullable String name) {
|
||||||
|
if (name == null) loadContactName();
|
||||||
@UiThread
|
else {
|
||||||
private void handlePrivateRequestAndResponse(PrivateMessageHeader h,
|
PrivateResponse m = (PrivateResponse) h;
|
||||||
String contactName) {
|
ConversationItem item = ConversationItem.from(
|
||||||
ConversationItem item;
|
ConversationActivity.this, name, m);
|
||||||
if (h instanceof PrivateRequest) {
|
addConversationItem(item);
|
||||||
PrivateRequest m = (PrivateRequest) h;
|
contactName.removeObserver(this);
|
||||||
item = ConversationItem
|
}
|
||||||
.from(ConversationActivity.this, contactName, m);
|
}
|
||||||
} else if (h instanceof PrivateResponse) {
|
});
|
||||||
PrivateResponse m = (PrivateResponse) h;
|
if (contactName.getValue() == null) loadContactName();
|
||||||
item = ConversationItem
|
} else {
|
||||||
.from(ConversationActivity.this, contactName, m);
|
addConversationItem(ConversationItem.from(h));
|
||||||
} else {
|
loadMessageBody(h.getId());
|
||||||
throw new AssertionError("Unknown PrivateMessageHeader");
|
}
|
||||||
}
|
});
|
||||||
addConversationItem(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markMessages(Collection<MessageId> messageIds, boolean sent,
|
private void markMessages(Collection<MessageId> messageIds, boolean sent,
|
||||||
@@ -804,10 +789,15 @@ public class ConversationActivity extends BriarActivity
|
|||||||
groupInvitationManager.respondToInvitation(contactId, id, accept);
|
groupInvitationManager.respondToInvitation(contactId, id, accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenableFutureTask<String> getContactNameTask() {
|
private void loadContactName() {
|
||||||
if (!contactNameTaskStarted.getAndSet(true))
|
runOnDbThread(() -> {
|
||||||
runOnDbThread(contactNameTask);
|
try {
|
||||||
return contactNameTask;
|
Contact c = contactManager.getContact(contactId);
|
||||||
|
contactName.postValue(c.getAuthor().getName());
|
||||||
|
} catch (DbException e) {
|
||||||
|
handleDbException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.thoughtcrime.securesms.components.util;
|
|
||||||
|
|
||||||
public interface FutureTaskListener<V> {
|
|
||||||
void onSuccess(V result);
|
|
||||||
|
|
||||||
void onFailure(Throwable error);
|
|
||||||
}
|
|
||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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<V> extends FutureTask<V> {
|
|
||||||
|
|
||||||
private final List<FutureTaskListener<V>> listeners = new LinkedList<>();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private final Object identifier;
|
|
||||||
|
|
||||||
public ListenableFutureTask(Callable<V> callable) {
|
|
||||||
this(callable, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ListenableFutureTask(Callable<V> 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<V> listener) {
|
|
||||||
if (this.isDone()) {
|
|
||||||
callback(listener);
|
|
||||||
} else {
|
|
||||||
this.listeners.add(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void removeListener(FutureTaskListener<V> listener) {
|
|
||||||
this.listeners.remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected synchronized void done() {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void callback() {
|
|
||||||
for (FutureTaskListener<V> listener : listeners) {
|
|
||||||
callback(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void callback(FutureTaskListener<V> 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user