summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik <roboerik@android.com>2010-03-29 18:20:32 -0700
committerErik <roboerik@android.com>2010-03-31 14:14:26 -0700
commita144f86b41170e8ee7fe8d966cc51c5fc90cd44a (patch)
tree75f9ae35fac03ed0a6c073f71667b2ff60f4b746
parent10b4b67d45c1e706b3323c1dacf390f783e6bc9f (diff)
downloadCalendar-a144f86b41170e8ee7fe8d966cc51c5fc90cd44a.tar.gz
b/2555049 Will only query accounts once when entering Calendars screen
There was noticeable jitter on entering the Calendars screen including misregistering taps due to the cursor requerying repeatedly during a sync. This change makes it so we only query on accounts once and then will requery every five seconds for about a minute. The view will only be updated if a change has occurred. Change-Id: I53610836e78d970d452d4c9724a2d3525cd85482
-rw-r--r--src/com/android/calendar/SelectCalendarsActivity.java37
-rw-r--r--src/com/android/calendar/SelectCalendarsAdapter.java114
-rw-r--r--src/com/android/calendar/Utils.java48
3 files changed, 109 insertions, 90 deletions
diff --git a/src/com/android/calendar/SelectCalendarsActivity.java b/src/com/android/calendar/SelectCalendarsActivity.java
index 74474886..5e46172d 100644
--- a/src/com/android/calendar/SelectCalendarsActivity.java
+++ b/src/com/android/calendar/SelectCalendarsActivity.java
@@ -21,6 +21,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.database.ContentObserver;
+import android.database.MatrixCursor;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Calendar.Calendars;
@@ -41,7 +42,6 @@ public class SelectCalendarsActivity extends ExpandableListActivity
private Cursor mCursor = null;
private ExpandableListView mList;
private SelectCalendarsAdapter mAdapter;
- private ContentResolver mContentResolver;
private static final String[] PROJECTION = new String[] {
Calendars._ID,
Calendars._SYNC_ACCOUNT_TYPE,
@@ -64,8 +64,9 @@ public class SelectCalendarsActivity extends ExpandableListActivity
"1) GROUP BY (_sync_account", //Cheap hack to make WHERE a GROUP BY query
null /* selectionArgs */,
Calendars._SYNC_ACCOUNT /*sort order*/);
- mContentResolver = getContentResolver();
- mAdapter = new SelectCalendarsAdapter(context, mCursor, this);
+ MatrixCursor accountsCursor = Utils.matrixCursorFromCursor(mCursor);
+ startManagingCursor(accountsCursor);
+ mAdapter = new SelectCalendarsAdapter(context, accountsCursor, this);
mList.setAdapter(mAdapter);
mList.setOnChildClickListener(this);
@@ -79,36 +80,6 @@ public class SelectCalendarsActivity extends ExpandableListActivity
for(int i = 0; i < count; i++) {
mList.expandGroup(i);
}
-
- }
-
- // Create an observer so that we can update the views whenever a
- // Calendar changes.
- private ContentObserver mObserver = new ContentObserver(new Handler())
- {
- @Override
- public boolean deliverSelfNotifications() {
- return true;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- if (!isFinishing()) {
- mCursor.requery();
- }
- }
- };
-
- @Override
- public void onPause() {
- super.onPause();
- mContentResolver.unregisterContentObserver(mObserver);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mContentResolver.registerContentObserver(Calendar.Events.CONTENT_URI, true, mObserver);
}
@Override
diff --git a/src/com/android/calendar/SelectCalendarsAdapter.java b/src/com/android/calendar/SelectCalendarsAdapter.java
index 47048f54..516cb1e4 100644
--- a/src/com/android/calendar/SelectCalendarsAdapter.java
+++ b/src/com/android/calendar/SelectCalendarsAdapter.java
@@ -48,6 +48,7 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
private static final String IS_PRIMARY = "\"primary\"";
private static final String CALENDARS_ORDERBY = IS_PRIMARY + " DESC," + Calendars.DISPLAY_NAME +
COLLATE_NOCASE;
+ private static final String ACCOUNT_SELECTION = Calendars._SYNC_ACCOUNT + "=?";
// The drawables used for the button to change the visible and sync states on a calendar
private static final int[] SYNC_VIS_BUTTON_RES = new int[] {
@@ -59,6 +60,7 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
private final LayoutInflater mInflater;
private final ContentResolver mResolver;
private final SelectCalendarsActivity mActivity;
+ private final View mView;
private Map<String, AuthenticatorDescription> mTypeToAuthDescription
= new HashMap<String, AuthenticatorDescription>();
protected AuthenticatorDescription[] mAuthDescs;
@@ -81,6 +83,12 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
// when a new update comes in, we'd like to leave a token space that won't be canceled.
private static final int MIN_UPDATE_TOKEN = 1000;
private static int mUpdateToken = MIN_UPDATE_TOKEN;
+ // How long to wait between requeries of the calendars to see if anything has changed.
+ private static final int REFRESH_DELAY = 5000;
+ // How long to keep refreshing for
+ private static final int REFRESH_DURATION = 60000;
+ private boolean mRefresh = true;
+ private int mNumAccounts;
private static String syncedVisible;
private static String syncedNotVisible;
@@ -121,22 +129,26 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
return;
}
+ // Set up a refresh for some point in the future if we haven't reached our max number
+ // of requeries yet. To make the code to track this easier we just use one count across
+ // all accounts and scale our max by the number of accounts.
+ if(mRefresh) {
+ mView.postDelayed(new RefreshCalendars(token, cookie), REFRESH_DELAY);
+ }
+
Cursor currentCursor = mChildrenCursors.get(cookie);
// Check if the new cursor has the same content as our old cursor
if (currentCursor != null) {
- if (compareCursors(currentCursor, cursor)) {
+ if (Utils.compareCursors(currentCursor, cursor)) {
cursor.close();
return;
- } else {
- mActivity.stopManagingCursor(currentCursor);
- currentCursor.close();
- mChildrenCursors.remove(cookie);
}
}
// If not then make a new matrix cursor for our Map
- MatrixCursor newCursor = matrixCursorFromCursor(cursor);
+ MatrixCursor newCursor = Utils.matrixCursorFromCursor(cursor);
+ cursor.close();
// And update our list of duplicated names
- Utils.checkForDuplicateNames(mIsDuplicateName, cursor, NAME_COLUMN);
+ Utils.checkForDuplicateNames(mIsDuplicateName, newCursor, NAME_COLUMN);
mChildrenCursors.put((String)cookie, newCursor);
try {
@@ -145,57 +157,17 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
} catch (NullPointerException e) {
Log.w(TAG, "Adapter expired, try again on the next query: " + e.getMessage());
}
- cursor.close();
- }
-
- /**
- * Compares two cursors to see if they contain the same data.
- *
- * @return Returns true of the cursors contain the same data and are not null, false
- * otherwise
- */
- private boolean compareCursors(Cursor c1, Cursor c2) {
- if(c1 == null || c2 == null) {
- return false;
- }
-
- int numColumns = c1.getColumnCount();
- if (numColumns != c2.getColumnCount()) {
- return false;
- }
-
- if (c1.getCount() != c2.getCount()) {
- return false;
- }
-
- c1.moveToPosition(-1);
- c2.moveToPosition(-1);
- while(c1.moveToNext() && c2.moveToNext()) {
- for(int i = 0; i < numColumns; i++) {
- if(!c1.getString(i).equals(c2.getString(i))) {
- return false;
- }
- }
- }
-
- return true;
- }
-
- private MatrixCursor matrixCursorFromCursor(Cursor cursor) {
- MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
- int numColumns = cursor.getColumnCount();
- String data[] = new String[numColumns];
- cursor.moveToPosition(-1);
- while (cursor.moveToNext()) {
- for (int i = 0; i < numColumns; i++) {
- data[i] = cursor.getString(i);
- }
- newCursor.addRow(data);
+ // Clean up our old cursor if we had one. We have to do this after setting the new
+ // cursor so that our view doesn't throw on an invalid cursor.
+ if (currentCursor != null) {
+ mActivity.stopManagingCursor(currentCursor);
+ currentCursor.close();
}
- return newCursor;
}
}
+
+
/**
* Method for changing the sync/vis state when a calendar's button is pressed.
*
@@ -253,7 +225,9 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
if (mCalendarsUpdater == null) {
mCalendarsUpdater = new AsyncCalendarsUpdater(mResolver);
}
- if(cursor.getCount() == 0) {
+
+ mNumAccounts = cursor.getCount();
+ if(mNumAccounts == 0) {
//Should never happen since Calendar requires an account exist to use it.
Log.e(TAG, "SelectCalendarsAdapter: No accounts were returned!");
}
@@ -262,6 +236,12 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
for (int i = 0; i < mAuthDescs.length; i++) {
mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
}
+ mView = mActivity.getExpandableListView();
+ mView.postDelayed(new Runnable() {
+ public void run() {
+ mRefresh = false;
+ }
+ }, REFRESH_DURATION);
}
/*
@@ -394,8 +374,8 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
mCalendarsUpdater.startQuery(groupCursor.getPosition(),
account,
Calendars.CONTENT_URI, PROJECTION,
- Calendars._SYNC_ACCOUNT + "=\"" + account + "\"" /*Selection*/,
- null /* selectionArgs */,
+ ACCOUNT_SELECTION,
+ new String[] { account } /*selectionArgs*/,
CALENDARS_ORDERBY);
return childCursor;
}
@@ -411,4 +391,24 @@ public class SelectCalendarsAdapter extends CursorTreeAdapter implements View.On
ViewGroup parent) {
return mInflater.inflate(R.layout.account_item, parent, false);
}
+
+ private class RefreshCalendars implements Runnable {
+
+ int mToken;
+ Object mAccount;
+
+ public RefreshCalendars(int token, Object cookie) {
+ mToken = token;
+ mAccount = cookie;
+ }
+
+ public void run() {
+ mCalendarsUpdater.startQuery(mToken,
+ mAccount,
+ Calendars.CONTENT_URI, PROJECTION,
+ ACCOUNT_SELECTION,
+ new String[] { mAccount.toString() } /*selectionArgs*/,
+ CALENDARS_ORDERBY);
+ }
+ }
}
diff --git a/src/com/android/calendar/Utils.java b/src/com/android/calendar/Utils.java
index 8b2660de..adba8214 100644
--- a/src/com/android/calendar/Utils.java
+++ b/src/com/android/calendar/Utils.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
+import android.database.MatrixCursor;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
@@ -91,6 +92,53 @@ public class Utils {
return time;
}
+ public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
+ MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
+ int numColumns = cursor.getColumnCount();
+ String data[] = new String[numColumns];
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ for (int i = 0; i < numColumns; i++) {
+ data[i] = cursor.getString(i);
+ }
+ newCursor.addRow(data);
+ }
+ return newCursor;
+ }
+
+ /**
+ * Compares two cursors to see if they contain the same data.
+ *
+ * @return Returns true of the cursors contain the same data and are not null, false
+ * otherwise
+ */
+ public static boolean compareCursors(Cursor c1, Cursor c2) {
+ if(c1 == null || c2 == null) {
+ return false;
+ }
+
+ int numColumns = c1.getColumnCount();
+ if (numColumns != c2.getColumnCount()) {
+ return false;
+ }
+
+ if (c1.getCount() != c2.getCount()) {
+ return false;
+ }
+
+ c1.moveToPosition(-1);
+ c2.moveToPosition(-1);
+ while(c1.moveToNext() && c2.moveToNext()) {
+ for(int i = 0; i < numColumns; i++) {
+ if(!c1.getString(i).equals(c2.getString(i))) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
/**
* If the given intent specifies a time (in milliseconds since the epoch),
* then that time is returned. Otherwise, the current time is returned.