From a88fbba49fa08a38adb7fe22dd1ff405414c57de Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Wed, 24 Sep 2014 13:54:56 -0700 Subject: [PATCH] use Loader when conversation is updated instead of requery // FREEBIE --- .../securesms/ConversationAdapter.java | 14 +-- .../securesms/ConversationListAdapter.java | 4 +- .../securesms/ConversationListFragment.java | 2 +- .../loaders/ConversationListLoader.java | 10 +-- .../database/loaders/ConversationLoader.java | 11 +-- .../securesms/util/AbstractCursorLoader.java | 90 +++++++++++++++++++ 6 files changed, 108 insertions(+), 23 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/util/AbstractCursorLoader.java diff --git a/src/org/thoughtcrime/securesms/ConversationAdapter.java b/src/org/thoughtcrime/securesms/ConversationAdapter.java index de7792b2a0..291f4a64e2 100644 --- a/src/org/thoughtcrime/securesms/ConversationAdapter.java +++ b/src/org/thoughtcrime/securesms/ConversationAdapter.java @@ -65,7 +65,7 @@ public class ConversationAdapter extends CursorAdapter implements AbsListView.Re public ConversationAdapter(Context context, MasterSecret masterSecret, Handler failedIconClickHandler, boolean groupThread, boolean pushDestination) { - super(context, null, true); + super(context, null, 0); this.context = context; this.masterSecret = masterSecret; this.failedIconClickHandler = failedIconClickHandler; @@ -84,6 +84,12 @@ public class ConversationAdapter extends CursorAdapter implements AbsListView.Re item.set(masterSecret, messageRecord, failedIconClickHandler, groupThread, pushDestination); } + @Override + public void changeCursor(Cursor cursor) { + messageRecordCache.clear(); + super.changeCursor(cursor); + } + @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view; @@ -148,12 +154,6 @@ public class ConversationAdapter extends CursorAdapter implements AbsListView.Re return messageRecord; } - @Override - protected void onContentChanged() { - super.onContentChanged(); - messageRecordCache.clear(); - } - public void close() { this.getCursor().close(); } diff --git a/src/org/thoughtcrime/securesms/ConversationListAdapter.java b/src/org/thoughtcrime/securesms/ConversationListAdapter.java index aac8240bcd..7ce87e34c4 100644 --- a/src/org/thoughtcrime/securesms/ConversationListAdapter.java +++ b/src/org/thoughtcrime/securesms/ConversationListAdapter.java @@ -18,11 +18,11 @@ package org.thoughtcrime.securesms; import android.content.Context; import android.database.Cursor; +import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; -import android.widget.CursorAdapter; import org.thoughtcrime.securesms.crypto.MasterCipher; import org.thoughtcrime.securesms.crypto.MasterSecret; @@ -50,7 +50,7 @@ public class ConversationListAdapter extends CursorAdapter implements AbsListVie private boolean batchMode = false; public ConversationListAdapter(Context context, Cursor cursor, MasterSecret masterSecret) { - super(context, cursor); + super(context, cursor, 0); if (masterSecret != null) this.masterCipher = new MasterCipher(masterSecret); else this.masterCipher = null; diff --git a/src/org/thoughtcrime/securesms/ConversationListFragment.java b/src/org/thoughtcrime/securesms/ConversationListFragment.java index 9e1c8ff1c5..b72fc2f48d 100644 --- a/src/org/thoughtcrime/securesms/ConversationListFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationListFragment.java @@ -32,6 +32,7 @@ import android.support.v7.app.ActionBarActivity; import android.support.v7.view.ActionMode; import android.support.v7.widget.SearchView; import android.util.Log; +import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -39,7 +40,6 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; -import android.widget.CursorAdapter; import android.widget.ListView; import org.thoughtcrime.securesms.components.DefaultSmsReminder; diff --git a/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java b/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java index a6dabb9787..f9e3ef5300 100644 --- a/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java +++ b/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java @@ -2,26 +2,24 @@ package org.thoughtcrime.securesms.database.loaders; import android.content.Context; import android.database.Cursor; -import android.support.v4.content.CursorLoader; import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.util.AbstractCursorLoader; import java.util.List; -public class ConversationListLoader extends CursorLoader { +public class ConversationListLoader extends AbstractCursorLoader { private final String filter; - private final Context context; public ConversationListLoader(Context context, String filter) { super(context); - this.filter = filter; - this.context = context.getApplicationContext(); + this.filter = filter; } @Override - public Cursor loadInBackground() { + public Cursor getCursor() { if (filter != null && filter.trim().length() != 0) { List numbers = ContactAccessor.getInstance() .getNumbersForThreadSearchFilter(filter, context.getContentResolver()); diff --git a/src/org/thoughtcrime/securesms/database/loaders/ConversationLoader.java b/src/org/thoughtcrime/securesms/database/loaders/ConversationLoader.java index a180daddb3..8b0c2f67d5 100644 --- a/src/org/thoughtcrime/securesms/database/loaders/ConversationLoader.java +++ b/src/org/thoughtcrime/securesms/database/loaders/ConversationLoader.java @@ -2,23 +2,20 @@ package org.thoughtcrime.securesms.database.loaders; import android.content.Context; import android.database.Cursor; -import android.support.v4.content.CursorLoader; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.util.AbstractCursorLoader; -public class ConversationLoader extends CursorLoader { - - private final Context context; - private final long threadId; +public class ConversationLoader extends AbstractCursorLoader { + private final long threadId; public ConversationLoader(Context context, long threadId) { super(context); - this.context = context.getApplicationContext(); this.threadId = threadId; } @Override - public Cursor loadInBackground() { + public Cursor getCursor() { return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId); } } diff --git a/src/org/thoughtcrime/securesms/util/AbstractCursorLoader.java b/src/org/thoughtcrime/securesms/util/AbstractCursorLoader.java new file mode 100644 index 0000000000..00afc8ca42 --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/AbstractCursorLoader.java @@ -0,0 +1,90 @@ +package org.thoughtcrime.securesms.util; + +import android.content.Context; +import android.database.Cursor; +import android.support.v4.content.AsyncTaskLoader; + +/** + * A Loader similar to CursorLoader that doesn't require queries to go through the ContentResolver + * to get the benefits of reloading when content has changed. + */ +public abstract class AbstractCursorLoader extends AsyncTaskLoader { + private static final String TAG = AbstractCursorLoader.class.getSimpleName(); + + protected final ForceLoadContentObserver observer; + protected final Context context; + protected Cursor cursor; + + public AbstractCursorLoader(Context context) { + super(context); + this.context = context.getApplicationContext(); + this.observer = new ForceLoadContentObserver(); + } + + public abstract Cursor getCursor(); + + @Override + public void deliverResult(Cursor newCursor) { + if (isReset()) { + if (newCursor != null) { + newCursor.close(); + } + return; + } + Cursor oldCursor = this.cursor; + + this.cursor = newCursor; + + if (isStarted()) { + super.deliverResult(newCursor); + } + if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { + oldCursor.close(); + } + } + + @Override + protected void onStartLoading() { + if (cursor != null) { + deliverResult(cursor); + } + if (takeContentChanged() || cursor == null) { + forceLoad(); + } + } + + @Override + protected void onStopLoading() { + cancelLoad(); + } + + @Override + public void onCanceled(Cursor cursor) { + if (cursor != null && !cursor.isClosed()) { + cursor.close(); + } + } + + @Override + public Cursor loadInBackground() { + Cursor newCursor = getCursor(); + if (newCursor != null) { + newCursor.getCount(); + newCursor.registerContentObserver(observer); + } + return newCursor; + } + + @Override + protected void onReset() { + super.onReset(); + + onStopLoading(); + + if (cursor != null && !cursor.isClosed()) { + cursor.close(); + } + cursor = null; + } + +}