Precompute cursor indexes in DocumentsUI and improve perf by 2.7%.
Relands after a revert, with a tiny fix.
Bug: 27286016
Change-Id: Ifb6cea46a86e8158b05db5dbf87878892c6cc702
diff --git a/src/com/android/documentsui/dirlist/Model.java b/src/com/android/documentsui/dirlist/Model.java
index c5ee592..179cb9b 100644
--- a/src/com/android/documentsui/dirlist/Model.java
+++ b/src/com/android/documentsui/dirlist/Model.java
@@ -20,8 +20,6 @@
import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME;
import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
import static com.android.documentsui.State.SORT_ORDER_SIZE;
-import static com.android.documentsui.model.DocumentInfo.getCursorLong;
-import static com.android.documentsui.model.DocumentInfo.getCursorString;
import android.database.Cursor;
import android.os.Bundle;
@@ -48,6 +46,7 @@
@VisibleForTesting
public class Model {
private static final String TAG = "Model";
+ private static final String EMPTY = "";
private boolean mIsLoading;
private List<UpdateListener> mUpdateListeners = new ArrayList<>();
@@ -62,6 +61,13 @@
private String mIds[] = new String[0];
private int mSortOrder = SORT_ORDER_DISPLAY_NAME;
+ private int mAuthorityIndex = -1;
+ private int mDocIdIndex = -1;
+ private int mMimeTypeIndex = -1;
+ private int mDisplayNameIndex = -1;
+ private int mSizeIndex = -1;
+ private int mLastModifiedIndex = -1;
+
@Nullable String info;
@Nullable String error;
@Nullable DocumentInfo doc;
@@ -72,20 +78,6 @@
*
* @param c A cursor that refers to a document.
*/
- private static String createModelId(Cursor c) {
- // TODO: Maybe more efficient to use just the document ID, in cases where there is only one
- // authority (which should be the majority of cases).
- return createModelId(
- getCursorString(c, RootCursorWrapper.COLUMN_AUTHORITY),
- getCursorString(c, Document.COLUMN_DOCUMENT_ID));
- }
-
- /**
- * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
- * string that can be used to identify the document referred to by the cursor.
- *
- * @param c A cursor that refers to a document.
- */
static String createModelId(String authority, String docId) {
return authority + "|" + docId;
}
@@ -127,6 +119,14 @@
mCursor = result.cursor;
mCursorCount = mCursor.getCount();
mSortOrder = result.sortOrder;
+ mAuthorityIndex = mCursor.getColumnIndex(RootCursorWrapper.COLUMN_AUTHORITY);
+ assert(mAuthorityIndex != -1);
+ mDocIdIndex = mCursor.getColumnIndex(Document.COLUMN_DOCUMENT_ID);
+ mMimeTypeIndex = mCursor.getColumnIndex(Document.COLUMN_MIME_TYPE);
+ mDisplayNameIndex = mCursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME);
+ mLastModifiedIndex = mCursor.getColumnIndex(Document.COLUMN_LAST_MODIFIED);
+ mSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE);
+
doc = result.doc;
updateModelData();
@@ -173,22 +173,24 @@
for (int pos = 0; pos < mCursorCount; ++pos) {
mCursor.moveToNext();
positions[pos] = pos;
- mIds[pos] = createModelId(mCursor);
- mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
+ // Generates a Model ID for a cursor entry that refers to a document. The Model ID is a
+ // unique string that can be used to identify the document referred to by the cursor.
+ mIds[pos] = createModelId(
+ getStringOrEmpty(mAuthorityIndex), getStringOrEmpty(mDocIdIndex));
+
+ mimeType = getStringOrEmpty(mMimeTypeIndex);
isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
- switch(mSortOrder) {
+ switch (mSortOrder) {
case SORT_ORDER_DISPLAY_NAME:
- final String displayName = getCursorString(
- mCursor, Document.COLUMN_DISPLAY_NAME);
- displayNames[pos] = displayName;
+ displayNames[pos] = getStringOrEmpty(mDisplayNameIndex);
break;
case SORT_ORDER_LAST_MODIFIED:
- longValues[pos] = getLastModified(mCursor);
+ longValues[pos] = getLastModified();
break;
case SORT_ORDER_SIZE:
- longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE);
+ longValues[pos] = getDocSize();
break;
}
}
@@ -244,7 +246,7 @@
} else {
final String lhs = pivotValue;
final String rhs = sortKey[mid];
- compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
+ compare = Shared.compareToIgnoreCase(lhs, rhs);
}
if (compare < 0) {
@@ -365,13 +367,42 @@
}
/**
- * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
- * timestamp - these will be replaced with MAX_LONG so that such files get sorted to the top
- * when sorting by date.
+ * @return Value of the string column, or an empty string if no value, or empty value.
*/
- long getLastModified(Cursor cursor) {
- long l = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED);
- return (l == -1) ? Long.MAX_VALUE : l;
+ private String getStringOrEmpty(int columnIndex) {
+ if (columnIndex == -1)
+ return EMPTY;
+ final String result = mCursor.getString(columnIndex);
+ return result != null ? result : EMPTY;
+ }
+
+ /**
+ * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
+ * or missing timestamp - these will be replaced with MAX_LONG so that such files get sorted to
+ * the top when sorting by date.
+ */
+ private long getLastModified() {
+ if (mLastModifiedIndex == -1)
+ return Long.MAX_VALUE;
+ try {
+ final long result = mCursor.getLong(mLastModifiedIndex);
+ return result > 0 ? result : Long.MAX_VALUE;
+ } catch (NumberFormatException e) {
+ return Long.MAX_VALUE;
+ }
+ }
+
+ /**
+ * @return Size for the given document. If the size is unknown or invalid, returns 0.
+ */
+ private long getDocSize() {
+ if (mSizeIndex == -1)
+ return 0;
+ try {
+ return mCursor.getLong(mSizeIndex);
+ } catch (NumberFormatException e) {
+ return 0;
+ }
}
public @Nullable Cursor getItem(String modelId) {