From 08fba5468fca507e003e7698feab55cbb0bb5f1f Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 25 Oct 2012 23:14:28 +0200 Subject: [PATCH] Switch MergeCursor from using a List to an array --- .../fsck/k9/fragment/MessageListFragment.java | 17 +- src/com/fsck/k9/helper/MergeCursor.java | 187 ++++++++++-------- .../k9/helper/MergeCursorWithUniqueId.java | 6 +- 3 files changed, 114 insertions(+), 96 deletions(-) diff --git a/src/com/fsck/k9/fragment/MessageListFragment.java b/src/com/fsck/k9/fragment/MessageListFragment.java index d61de81b0..c58fd1df7 100644 --- a/src/com/fsck/k9/fragment/MessageListFragment.java +++ b/src/com/fsck/k9/fragment/MessageListFragment.java @@ -338,7 +338,7 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick private String[] mAccountUuids; private int mUnreadMessageCount = 0; - private Map mCursors = new HashMap(); + private Cursor[] mCursors; /** * Stores the name of the folder that we want to open as soon as possible @@ -700,7 +700,9 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick initializeMessageList(); LoaderManager loaderManager = getLoaderManager(); - for (int i = 0, len = mAccountUuids.length; i < len; i++) { + int len = mAccountUuids.length; + mCursors = new Cursor[len]; + for (int i = 0; i < len; i++) { loaderManager.initLoader(i, null, this); } } @@ -2757,16 +2759,9 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick @Override public void onLoadFinished(Loader loader, Cursor data) { - mCursors.put(loader.getId(), data); + mCursors[loader.getId()] = data; - List list = new LinkedList(mCursors.keySet()); - Collections.sort(list); - List cursors = new ArrayList(list.size()); - for (Integer id : list) { - cursors.add(mCursors.get(id)); - } - - MergeCursorWithUniqueId cursor = new MergeCursorWithUniqueId(cursors); + MergeCursorWithUniqueId cursor = new MergeCursorWithUniqueId(mCursors); mSelected = new SparseBooleanArray(cursor.getCount()); //TODO: use the (stable) IDs as index and reuse the old mSelected diff --git a/src/com/fsck/k9/helper/MergeCursor.java b/src/com/fsck/k9/helper/MergeCursor.java index efba70d23..1edc6360c 100644 --- a/src/com/fsck/k9/helper/MergeCursor.java +++ b/src/com/fsck/k9/helper/MergeCursor.java @@ -1,7 +1,23 @@ +/* + * Copyright (C) 2012 The K-9 Dog Walkers + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.fsck.k9.helper; -import java.util.List; - +import android.annotation.TargetApi; import android.content.ContentResolver; import android.database.CharArrayBuffer; import android.database.ContentObserver; @@ -18,7 +34,7 @@ public class MergeCursor implements Cursor { /** * List of the cursors combined in this object. */ - protected final List mCursors; + protected final Cursor[] mCursors; /** * The currently active cursor. @@ -32,6 +48,8 @@ public class MergeCursor implements Cursor { */ protected int mActiveCursorIndex; + protected int mPosition; + /** * Used to cache the value of {@link #getCount()} */ @@ -44,16 +62,24 @@ public class MergeCursor implements Cursor { * @param cursors * The list of cursors this {@code MultiCursor} should combine. */ - public MergeCursor(List cursors) { - mCursors = cursors; - mActiveCursorIndex = 0; - mActiveCursor = cursors.get(0); + public MergeCursor(Cursor[] cursors) { + mCursors = cursors.clone(); + + for (int i = 0, len = mCursors.length; i < len; i++) { + if (mCursors[i] != null) { + mActiveCursorIndex = i; + mActiveCursor = mCursors[mActiveCursorIndex]; + } + } + mPosition = -1; } @Override public void close() { for (Cursor cursor : mCursors) { - cursor.close(); + if (cursor != null) { + cursor.close(); + } } } @@ -65,7 +91,9 @@ public class MergeCursor implements Cursor { @Override public void deactivate() { for (Cursor cursor : mCursors) { - cursor.deactivate(); + if (cursor != null) { + cursor.deactivate(); + } } } @@ -105,7 +133,9 @@ public class MergeCursor implements Cursor { if (mCount == -1) { int count = 0; for (Cursor cursor : mCursors) { - count += cursor.getCount(); + if (cursor != null) { + count += cursor.getCount(); + } } mCount = count; @@ -136,12 +166,7 @@ public class MergeCursor implements Cursor { @Override public int getPosition() { - int pos = 0; - for (int i = 0; i < mActiveCursorIndex; i++) { - pos += mCursors.get(i).getCount(); - } - - return pos + mActiveCursor.getPosition(); + return mPosition; } @Override @@ -154,6 +179,7 @@ public class MergeCursor implements Cursor { return mActiveCursor.getString(columnIndex); } + @TargetApi(11) @Override public int getType(int columnIndex) { return mActiveCursor.getType(columnIndex); @@ -166,20 +192,21 @@ public class MergeCursor implements Cursor { @Override public boolean isAfterLast() { - if (mActiveCursorIndex == mCursors.size() - 1) { - return mActiveCursor.isAfterLast(); + int count = getCount(); + if (count == 0) { + return true; } - return false; + return (mPosition == count); } @Override public boolean isBeforeFirst() { - if (mActiveCursorIndex == 0) { - return mActiveCursor.isBeforeFirst(); + if (getCount() == 0) { + return true; } - return false; + return (mPosition == -1); } @Override @@ -189,20 +216,21 @@ public class MergeCursor implements Cursor { @Override public boolean isFirst() { - if (mActiveCursorIndex == 0) { - return mActiveCursor.isFirst(); + if (getCount() == 0) { + return false; } - return false; + return (mPosition == 0); } @Override public boolean isLast() { - if (mActiveCursorIndex == mCursors.size() - 1) { - return mActiveCursor.isLast(); + int count = getCount(); + if (count == 0) { + return false; } - return false; + return (mPosition == (count - 1)); } @Override @@ -212,81 +240,78 @@ public class MergeCursor implements Cursor { @Override public boolean move(int offset) { - int ofs = offset; - int pos = mActiveCursor.getPosition(); - if (offset >= 0) { - while (pos + ofs > mActiveCursor.getCount() & - mActiveCursorIndex < mCursors.size() - 1) { - - // Adjust the "move offset" - ofs -= mActiveCursor.getCount() - pos; - - // Move to the next cursor - mActiveCursor = mCursors.get(++mActiveCursorIndex); - - // Move the new cursor to the first position - mActiveCursor.moveToFirst(); - pos = 0; - } - } else { - while (pos + ofs < 0 && mActiveCursorIndex > 0) { - // Adjust the "move offset" - ofs += pos; - - // Move to the next cursor - mActiveCursor = mCursors.get(--mActiveCursorIndex); - - // Move the new cursor to the first position - mActiveCursor.moveToLast(); - pos = mActiveCursor.getPosition(); - } - } - - return mActiveCursor.move(ofs); + return moveToPosition(mPosition + offset); } @Override public boolean moveToFirst() { - mActiveCursorIndex = 0; - mActiveCursor = mCursors.get(mActiveCursorIndex); - return mActiveCursor.moveToFirst(); + return moveToPosition(0); } @Override public boolean moveToLast() { - mActiveCursorIndex = mCursors.size() - 1; - mActiveCursor = mCursors.get(mActiveCursorIndex); - return mActiveCursor.moveToLast(); + return moveToPosition(getCount() - 1); } @Override public boolean moveToNext() { - return move(1); + return moveToPosition(mPosition + 1); } @Override public boolean moveToPosition(int position) { - // Start at the beginning - mActiveCursorIndex = 0; - mActiveCursor = mCursors.get(mActiveCursorIndex); - - int pos = position; - while (pos > mActiveCursor.getCount() - 1 && - mActiveCursorIndex < mCursors.size() - 1) { - - // Adjust the position - pos -= mActiveCursor.getCount(); - - // Move to the next cursor - mActiveCursor = mCursors.get(++mActiveCursorIndex); + // Make sure position isn't past the end of the cursor + final int count = getCount(); + if (position >= count) { + mPosition = count; + return false; } - return mActiveCursor.moveToPosition(pos); + // Make sure position isn't before the beginning of the cursor + if (position < 0) { + mPosition = -1; + return false; + } + + // Check for no-op moves, and skip the rest of the work for them + if (position == mPosition) { + return true; + } + + /* Find the right cursor */ + mActiveCursor = null; + mActiveCursorIndex = -1; + mPosition = -1; + int cursorStartPos = 0; + + for (int i = 0, len = mCursors.length; i < len; i++) { + if (mCursors[i] == null) { + continue; + } + + if (position < (cursorStartPos + mCursors[i].getCount())) { + mActiveCursorIndex = i; + mActiveCursor = mCursors[mActiveCursorIndex]; + break; + } + + cursorStartPos += mCursors[i].getCount(); + } + + /* Move it to the right position */ + if (mActiveCursor != null) { + boolean success = mActiveCursor.moveToPosition(position - cursorStartPos); + mPosition = (success) ? position : -1; + + return success; + } + + return false; } @Override public boolean moveToPrevious() { - return move(-1); + return moveToPosition(mPosition - 1); } @Override diff --git a/src/com/fsck/k9/helper/MergeCursorWithUniqueId.java b/src/com/fsck/k9/helper/MergeCursorWithUniqueId.java index 284fcf9f4..7cad2b084 100644 --- a/src/com/fsck/k9/helper/MergeCursorWithUniqueId.java +++ b/src/com/fsck/k9/helper/MergeCursorWithUniqueId.java @@ -1,7 +1,5 @@ package com.fsck.k9.helper; -import java.util.List; - import android.database.Cursor; @@ -14,10 +12,10 @@ public class MergeCursorWithUniqueId extends MergeCursor { private int mIdColumnIndex = -1; - public MergeCursorWithUniqueId(List cursors) { + public MergeCursorWithUniqueId(Cursor[] cursors) { super(cursors); - if (cursors.size() > MAX_CURSORS) { + if (cursors.length > MAX_CURSORS) { throw new IllegalArgumentException("This class only supports up to " + MAX_CURSORS + " cursors"); }