kopia lustrzana https://github.com/ryukoposting/Signal-Android
Fetch isQuoted status in bulk during conversation load.
Improves overall time to load a page of messages by ~50%.main
rodzic
c6f29fc950
commit
a84a9c5381
|
@ -93,10 +93,11 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
|
||||
@Override
|
||||
public @NonNull List<ConversationMessage> load(int start, int length, @NonNull CancellationSignal cancellationSignal) {
|
||||
Stopwatch stopwatch = new Stopwatch("load(" + start + ", " + length + "), thread " + threadId);
|
||||
MmsSmsTable db = SignalDatabase.mmsSms();
|
||||
List<MessageRecord> records = new ArrayList<>(length);
|
||||
Stopwatch stopwatch = new Stopwatch("load(" + start + ", " + length + "), thread " + threadId);
|
||||
MmsSmsTable db = SignalDatabase.mmsSms();
|
||||
List<MessageRecord> records = new ArrayList<>(length);
|
||||
MentionHelper mentionHelper = new MentionHelper();
|
||||
QuotedHelper quotedHelper = new QuotedHelper();
|
||||
AttachmentHelper attachmentHelper = new AttachmentHelper();
|
||||
ReactionHelper reactionHelper = new ReactionHelper();
|
||||
PaymentHelper paymentHelper = new PaymentHelper();
|
||||
|
@ -107,6 +108,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
while ((record = reader.getNext()) != null && !cancellationSignal.isCanceled()) {
|
||||
records.add(record);
|
||||
mentionHelper.add(record);
|
||||
quotedHelper.add(record);
|
||||
reactionHelper.add(record);
|
||||
attachmentHelper.add(record);
|
||||
paymentHelper.add(record);
|
||||
|
@ -131,6 +133,9 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
mentionHelper.fetchMentions(context);
|
||||
stopwatch.split("mentions");
|
||||
|
||||
quotedHelper.fetchQuotedState();
|
||||
stopwatch.split("is-quoted");
|
||||
|
||||
reactionHelper.fetchReactions();
|
||||
stopwatch.split("reactions");
|
||||
|
||||
|
@ -155,7 +160,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
stopwatch.split("recipient-resolves");
|
||||
|
||||
List<ConversationMessage> messages = Stream.of(records)
|
||||
.map(m -> ConversationMessageFactory.createWithUnresolvedData(context, m, mentionHelper.getMentions(m.getId())))
|
||||
.map(m -> ConversationMessageFactory.createWithUnresolvedData(context, m, mentionHelper.getMentions(m.getId()), quotedHelper.isQuoted(m.getId())))
|
||||
.toList();
|
||||
|
||||
stopwatch.split("conversion");
|
||||
|
@ -180,28 +185,27 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
try {
|
||||
if (record != null) {
|
||||
List<Mention> mentions = SignalDatabase.mentions().getMentionsForMessage(messageId.getId());
|
||||
|
||||
stopwatch.split("mentions");
|
||||
|
||||
boolean isQuoted = SignalDatabase.mmsSms().isQuoted(record);
|
||||
stopwatch.split("is-quoted");
|
||||
|
||||
List<ReactionRecord> reactions = SignalDatabase.reactions().getReactions(messageId);
|
||||
record = ReactionHelper.recordWithReactions(record, reactions);
|
||||
|
||||
stopwatch.split("reactions");
|
||||
|
||||
List<DatabaseAttachment> attachments = SignalDatabase.attachments().getAttachmentsForMessage(messageId.getId());
|
||||
if (attachments.size() > 0) {
|
||||
record = ((MediaMmsMessageRecord) record).withAttachments(context, attachments);
|
||||
}
|
||||
|
||||
stopwatch.split("attachments");
|
||||
|
||||
if (record.isPaymentNotification()) {
|
||||
record = SignalDatabase.payments().updateMessageWithPayment(record);
|
||||
}
|
||||
|
||||
stopwatch.split("payments");
|
||||
|
||||
return ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(ApplicationDependencies.getApplication(), record, mentions);
|
||||
return ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(ApplicationDependencies.getApplication(), record, mentions, isQuoted);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -235,6 +239,24 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
}
|
||||
}
|
||||
|
||||
private static class QuotedHelper {
|
||||
|
||||
private Collection<MessageRecord> records = new LinkedList<>();
|
||||
private Set<Long> hasBeenQuotedIds = new HashSet<>();
|
||||
|
||||
void add(MessageRecord record) {
|
||||
records.add(record);
|
||||
}
|
||||
|
||||
void fetchQuotedState() {
|
||||
hasBeenQuotedIds = SignalDatabase.mmsSms().isQuoted(records);
|
||||
}
|
||||
|
||||
boolean isQuoted(long id) {
|
||||
return hasBeenQuotedIds.contains(id);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AttachmentHelper {
|
||||
|
||||
private Collection<Long> messageIds = new LinkedList<>();
|
||||
|
|
|
@ -35,10 +35,6 @@ public class ConversationMessage {
|
|||
@NonNull private final MessageStyler.Result styleResult;
|
||||
private final boolean hasBeenQuoted;
|
||||
|
||||
private ConversationMessage(@NonNull MessageRecord messageRecord) {
|
||||
this(messageRecord, null, null, false);
|
||||
}
|
||||
|
||||
private ConversationMessage(@NonNull MessageRecord messageRecord, boolean hasBeenQuoted) {
|
||||
this(messageRecord, null, null, hasBeenQuoted);
|
||||
}
|
||||
|
@ -165,9 +161,7 @@ public class ConversationMessage {
|
|||
* @param mentions List of placeholder mentions to be used to update the body in the provided MessageRecord.
|
||||
*/
|
||||
@WorkerThread
|
||||
public static @NonNull ConversationMessage createWithUnresolvedData(@NonNull Context context, @NonNull MessageRecord messageRecord, @Nullable List<Mention> mentions) {
|
||||
boolean hasBeenQuoted = SignalDatabase.mmsSms().isQuoted(messageRecord);
|
||||
|
||||
public static @NonNull ConversationMessage createWithUnresolvedData(@NonNull Context context, @NonNull MessageRecord messageRecord, @Nullable List<Mention> mentions, boolean hasBeenQuoted) {
|
||||
if (messageRecord.isMms() && mentions != null && !mentions.isEmpty()) {
|
||||
MentionUtil.UpdatedBodyAndMentions updated = MentionUtil.updateBodyAndMentionsWithDisplayNames(context, messageRecord, mentions);
|
||||
return new ConversationMessage(messageRecord, updated.getBody(), updated.getMentions(), hasBeenQuoted);
|
||||
|
|
|
@ -52,10 +52,12 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -261,6 +263,42 @@ public class MmsSmsTable extends DatabaseTable {
|
|||
return queryTables(PROJECTION, selection, order, null, true);
|
||||
}
|
||||
|
||||
public Set<Long> isQuoted(@NonNull Collection<MessageRecord> records) {
|
||||
if (records.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
Map<QuoteDescriptor, MessageRecord> byQuoteDescriptor = new HashMap<>(records.size());
|
||||
List<String[]> args = new ArrayList<>(records.size());
|
||||
|
||||
for (MessageRecord record : records) {
|
||||
long timestamp = record.getDateSent();
|
||||
RecipientId author = record.isOutgoing() ? Recipient.self().getId() : record.getRecipient().getId();
|
||||
|
||||
byQuoteDescriptor.put(new QuoteDescriptor(timestamp, author), record);
|
||||
args.add(SqlUtil.buildArgs(timestamp, author));
|
||||
}
|
||||
|
||||
|
||||
String[] projection = new String[] { MessageTable.QUOTE_ID, MessageTable.QUOTE_AUTHOR };
|
||||
List<SqlUtil.Query> queries = SqlUtil.buildCustomCollectionQuery(MessageTable.QUOTE_ID + " = ? AND " + MessageTable.QUOTE_AUTHOR + " = ?", args);
|
||||
Set<Long> quotedIds = new HashSet<>();
|
||||
|
||||
for (SqlUtil.Query query : queries) {
|
||||
try (Cursor cursor = getReadableDatabase().query(MessageTable.TABLE_NAME, projection, query.getWhere(), query.getWhereArgs(), null, null, null)) {
|
||||
while (cursor.moveToNext()) {
|
||||
long timestamp = CursorUtil.requireLong(cursor, MessageTable.QUOTE_ID);
|
||||
RecipientId author = RecipientId.from(CursorUtil.requireString(cursor, MessageTable.QUOTE_AUTHOR));
|
||||
QuoteDescriptor quoteLocator = new QuoteDescriptor(timestamp, author);
|
||||
|
||||
quotedIds.add(byQuoteDescriptor.get(quoteLocator).getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return quotedIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the message has been quoted by another message.
|
||||
*/
|
||||
|
@ -984,4 +1022,27 @@ public class MmsSmsTable extends DatabaseTable {
|
|||
this.threads = threads;
|
||||
}
|
||||
}
|
||||
|
||||
private static class QuoteDescriptor {
|
||||
private final long timestamp;
|
||||
private final RecipientId author;
|
||||
|
||||
private QuoteDescriptor(long timestamp, RecipientId author) {
|
||||
this.author = author;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final QuoteDescriptor that = (QuoteDescriptor) o;
|
||||
return timestamp == that.timestamp && author.equals(that.author);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(author, timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue