diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index b6fec54638..10fb4ee141 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -146,6 +146,7 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi public void onStart(@NonNull LifecycleOwner owner) { isAppVisible = true; Log.i(TAG, "App is now visible."); + ApplicationDependencies.getRecipientCache().warmUp(); executePendingContactSync(); KeyCachingService.onAppForegrounded(this); } diff --git a/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java b/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java index d3f0f35f0e..571d9e0fef 100644 --- a/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java +++ b/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java @@ -125,8 +125,6 @@ public final class LiveRecipient { if (Util.isMainThread()) { Log.w(TAG, "[Resolve][MAIN] " + getId(), new Throwable()); - } else { - Log.d(TAG, "[Resolve][" + Thread.currentThread().getName() + "] " + getId()); } Recipient updated = fetchRecipientFromDisk(getId()); @@ -154,8 +152,6 @@ public final class LiveRecipient { if (Util.isMainThread()) { Log.w(TAG, "[Refresh][MAIN] " + getId(), new Throwable()); - } else { - Log.d(TAG, "[Refresh][" + Thread.currentThread().getName() + "] " + getId()); } Recipient recipient = fetchRecipientFromDisk(getId()); diff --git a/src/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java b/src/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java index 06e3e53a50..510ed65058 100644 --- a/src/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java +++ b/src/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java @@ -2,23 +2,37 @@ package org.thoughtcrime.securesms.recipients; import android.annotation.SuppressLint; import android.content.Context; +import android.database.Cursor; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; import androidx.lifecycle.MutableLiveData; +import com.annimon.stream.Stream; + import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase.MissingRecipientError; +import org.thoughtcrime.securesms.database.ThreadDatabase; +import org.thoughtcrime.securesms.database.model.ThreadRecord; +import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.util.LRUCache; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Map; public final class LiveRecipientCache { + private static final String TAG = Log.tag(LiveRecipientCache.class); + + private static final int CACHE_MAX = 1000; + private static final int CACHE_WARM_MAX = 500; private final Context context; private final RecipientDatabase recipientDatabase; @@ -26,12 +40,13 @@ public final class LiveRecipientCache { private final LiveRecipient unknown; private RecipientId localRecipientId; + private boolean warmedUp; @SuppressLint("UseSparseArrays") public LiveRecipientCache(@NonNull Context context) { this.context = context.getApplicationContext(); this.recipientDatabase = DatabaseFactory.getRecipientDatabase(context); - this.recipients = new LRUCache<>(1000); + this.recipients = new LRUCache<>(CACHE_MAX); this.unknown = new LiveRecipient(context, new MutableLiveData<>(), Recipient.UNKNOWN); } @@ -71,4 +86,33 @@ public final class LiveRecipientCache { return getLive(localRecipientId).resolve(); } + + @AnyThread + public synchronized void warmUp() { + if (warmedUp) { + return; + } else { + warmedUp = true; + } + + SignalExecutors.BOUNDED.execute(() -> { + ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context); + + try (ThreadDatabase.Reader reader = threadDatabase.readerFor(threadDatabase.getConversationList())) { + int i = 0; + ThreadRecord record = null; + List recipients = new ArrayList<>(); + + while ((record = reader.getNext()) != null && i < CACHE_WARM_MAX) { + recipients.add(record.getRecipient()); + i++; + } + + Log.d(TAG, "Warming up " + recipients.size() + " recipients."); + + Collections.reverse(recipients); + Stream.of(recipients).map(Recipient::getId).forEach(this::getLive); + } + }); + } }