Save the state of checkboxes when orientation is changed

BUG: 2239516

* Add tests for save/restore Instance State
This commit is contained in:
satok 2009-11-16 18:33:13 +09:00
parent 5660af68e9
commit 4cb25d93a2
2 changed files with 268 additions and 4 deletions

View File

@ -86,6 +86,8 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
"com.android.email.activity.MessageList.selectedItemTop"; "com.android.email.activity.MessageList.selectedItemTop";
private static final String STATE_SELECTED_POSITION = private static final String STATE_SELECTED_POSITION =
"com.android.email.activity.MessageList.selectedPosition"; "com.android.email.activity.MessageList.selectedPosition";
private static final String STATE_CHECKED_ITEMS =
"com.android.email.activity.MessageList.checkedItems";
// UI support // UI support
private ListView mListView; private ListView mListView;
@ -354,6 +356,14 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
saveListPosition(); saveListPosition();
outState.putInt(STATE_SELECTED_POSITION, mSavedItemPosition); outState.putInt(STATE_SELECTED_POSITION, mSavedItemPosition);
outState.putInt(STATE_SELECTED_ITEM_TOP, mSavedItemTop); outState.putInt(STATE_SELECTED_ITEM_TOP, mSavedItemTop);
Set<Long> checkedset = mListAdapter.getSelectedSet();
long[] checkedarray = new long[checkedset.size()];
int i = 0;
for (Long l : checkedset) {
checkedarray[i] = l;
i++;
}
outState.putLongArray(STATE_CHECKED_ITEMS, checkedarray);
} }
@Override @Override
@ -361,11 +371,15 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
super.onRestoreInstanceState(savedInstanceState); super.onRestoreInstanceState(savedInstanceState);
mSavedItemTop = savedInstanceState.getInt(STATE_SELECTED_ITEM_TOP, 0); mSavedItemTop = savedInstanceState.getInt(STATE_SELECTED_ITEM_TOP, 0);
mSavedItemPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION, -1); mSavedItemPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION, -1);
Set<Long> checkedset = mListAdapter.getSelectedSet();
for (long l: savedInstanceState.getLongArray(STATE_CHECKED_ITEMS)) {
checkedset.add(l);
}
} }
private void saveListPosition() { private void saveListPosition() {
mSavedItemPosition = getListView().getSelectedItemPosition(); mSavedItemPosition = getListView().getSelectedItemPosition();
if (mSavedItemPosition >= 0) { if (mSavedItemPosition >= 0 && getListView().isSelected()) {
mSavedItemTop = getListView().getSelectedView().getTop(); mSavedItemTop = getListView().getSelectedView().getTop();
} else { } else {
mSavedItemPosition = getListView().getFirstVisiblePosition(); mSavedItemPosition = getListView().getFirstVisiblePosition();
@ -1411,7 +1425,7 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
/** /**
* This class implements the adapter for displaying messages based on cursors. * This class implements the adapter for displaying messages based on cursors.
*/ */
/* package */ class MessageListAdapter extends CursorAdapter { /* package */ public class MessageListAdapter extends CursorAdapter {
public static final int COLUMN_ID = 0; public static final int COLUMN_ID = 0;
public static final int COLUMN_MAILBOX_KEY = 1; public static final int COLUMN_MAILBOX_KEY = 1;
@ -1449,7 +1463,6 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
private static final long REFRESH_INTERVAL_MS = 2500; private static final long REFRESH_INTERVAL_MS = 2500;
private java.text.DateFormat mDateFormat; private java.text.DateFormat mDateFormat;
private java.text.DateFormat mDayFormat;
private java.text.DateFormat mTimeFormat; private java.text.DateFormat mTimeFormat;
private HashSet<Long> mChecked = new HashSet<Long>(); private HashSet<Long> mChecked = new HashSet<Long>();
@ -1474,7 +1487,6 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
mTextColorSecondary = resources.getColorStateList(array.getResourceId(0, 0)); mTextColorSecondary = resources.getColorStateList(array.getResourceId(0, 0));
mDateFormat = android.text.format.DateFormat.getDateFormat(context); // short date mDateFormat = android.text.format.DateFormat.getDateFormat(context); // short date
mDayFormat = android.text.format.DateFormat.getDateFormat(context); // TODO: day
mTimeFormat = android.text.format.DateFormat.getTimeFormat(context); // 12/24 time mTimeFormat = android.text.format.DateFormat.getTimeFormat(context); // 12/24 time
} }

View File

@ -0,0 +1,252 @@
/*
* Copyright (C) 2009 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.android.email.activity;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.MessageColumns;
import android.app.Application;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.CursorIndexOutOfBoundsException;
import android.database.AbstractCursor;
import android.database.SQLException;
import android.os.Bundle;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.test.suitebuilder.annotation.LargeTest;
import android.widget.ListAdapter;
import android.widget.CursorAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Various instrumentation tests for MessageList.
*
* It might be possible to convert these to ActivityUnitTest, which would be faster.
*/
@LargeTest
public class MessageListUnitTests
extends ActivityInstrumentationTestCase2<MessageList> {
private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity._ACCOUNT_ID";
private static final String EXTRA_MAILBOX_TYPE = "com.android.email.activity.MAILBOX_TYPE";
private static final String EXTRA_MAILBOX_ID = "com.android.email.activity.MAILBOX_ID";
private static final String STATE_SELECTED_ITEM_TOP =
"com.android.email.activity.MessageList.selectedItemTop";
private static final String STATE_SELECTED_POSITION =
"com.android.email.activity.MessageList.selectedPosition";
private static final String STATE_CHECKED_ITEMS =
"com.android.email.activity.MessageList.checkedItems";
public final String[] PROJECTION = new String[] {
EmailContent.RECORD_ID, MessageColumns.MAILBOX_KEY, MessageColumns.ACCOUNT_KEY,
MessageColumns.DISPLAY_NAME, MessageColumns.SUBJECT, MessageColumns.TIMESTAMP,
MessageColumns.FLAG_READ, MessageColumns.FLAG_FAVORITE, MessageColumns.FLAG_ATTACHMENT,
};
private Context mContext;
private MessageList mMessageList;
private CursorAdapter mListAdapter;
private HashMap<Long, Map<String, Object>> mRowsMap;
private ArrayList<Long> mIDarray;
public MessageListUnitTests() {
super("com.android.email", MessageList.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getTargetContext();
Email.setServicesEnabled(mContext);
Intent i = new Intent()
.putExtra(EXTRA_ACCOUNT_ID, Long.MIN_VALUE)
.putExtra(EXTRA_MAILBOX_TYPE, Long.MIN_VALUE)
.putExtra(EXTRA_MAILBOX_ID, Long.MIN_VALUE);
this.setActivityIntent(i);
mMessageList = getActivity();
}
/**
* Add a dummy message to the data map
*/
private void addElement(long id, long mailboxKey, long accountKey, String displayName,
String subject, long timestamp, int flagRead, int flagFavorite, int flagAttachment) {
HashMap<String, Object> emap = new HashMap<String, Object>();
emap.put(EmailContent.RECORD_ID, id);
emap.put(MessageColumns.MAILBOX_KEY, mailboxKey);
emap.put(MessageColumns.ACCOUNT_KEY, accountKey);
emap.put(MessageColumns.DISPLAY_NAME, displayName);
emap.put(MessageColumns.SUBJECT, subject);
emap.put(MessageColumns.TIMESTAMP, timestamp);
emap.put(MessageColumns.FLAG_READ, flagRead);
emap.put(MessageColumns.FLAG_FAVORITE, flagFavorite);
emap.put(MessageColumns.FLAG_ATTACHMENT, flagAttachment);
mRowsMap.put(id, emap);
mIDarray.add(id);
}
/**
* Create dummy messages
*/
private void setUpCustomCursor() throws Throwable {
runTestOnUiThread(new Runnable() {
public void run() {
mListAdapter = (CursorAdapter)mMessageList.getListAdapter();
mRowsMap = new HashMap<Long, Map<String, Object>>(0);
mIDarray = new ArrayList<Long>(0);
addElement(0, Long.MIN_VALUE, Long.MIN_VALUE, "a", "A", 0, 0, 0, 0);
addElement(1, Long.MIN_VALUE, Long.MIN_VALUE, "b", "B", 0, 0, 0, 0);
addElement(2, Long.MIN_VALUE, Long.MIN_VALUE, "c", "C", 0, 0, 0, 0);
addElement(3, Long.MIN_VALUE, Long.MIN_VALUE, "d", "D", 0, 0, 0, 0);
addElement(4, Long.MIN_VALUE, Long.MIN_VALUE, "e", "E", 0, 0, 0, 0);
addElement(5, Long.MIN_VALUE, Long.MIN_VALUE, "f", "F", 0, 0, 0, 0);
addElement(6, Long.MIN_VALUE, Long.MIN_VALUE, "g", "G", 0, 0, 0, 0);
addElement(7, Long.MIN_VALUE, Long.MIN_VALUE, "h", "H", 0, 0, 0, 0);
addElement(8, Long.MIN_VALUE, Long.MIN_VALUE, "i", "I", 0, 0, 0, 0);
addElement(9, Long.MIN_VALUE, Long.MIN_VALUE, "j", "J", 0, 0, 0, 0);
CustomCursor cc = new CustomCursor(mIDarray, PROJECTION, mRowsMap);
mListAdapter.changeCursor(cc);
}
});
}
public void testRestoreAndSaveInstanceState() throws Throwable {
setUpCustomCursor();
Bundle bundle = new Bundle();
mMessageList.onSaveInstanceState(bundle);
long[] checkedarray = bundle.getLongArray(STATE_CHECKED_ITEMS);
assertEquals(0, checkedarray.length);
Set<Long> checkedset = ((MessageList.MessageListAdapter)mListAdapter).getSelectedSet();
checkedset.add(1L);
checkedset.add(3L);
checkedset.add(5L);
mMessageList.onSaveInstanceState(bundle);
checkedarray = bundle.getLongArray(STATE_CHECKED_ITEMS);
java.util.Arrays.sort(checkedarray);
assertEquals(3, checkedarray.length);
assertEquals(1, checkedarray[0]);
assertEquals(3, checkedarray[1]);
assertEquals(5, checkedarray[2]);
}
public void testRestoreInstanceState() throws Throwable {
setUpCustomCursor();
Bundle bundle = new Bundle();
long[] checkedarray = new long[3];
checkedarray[0] = 1;
checkedarray[1] = 3;
checkedarray[2] = 5;
Set<Long> checkedset = ((MessageList.MessageListAdapter)mListAdapter).getSelectedSet();
assertEquals(0, checkedset.size());
bundle.putLongArray(STATE_CHECKED_ITEMS, checkedarray);
mMessageList.onRestoreInstanceState(bundle);
checkedset = ((MessageList.MessageListAdapter)mListAdapter).getSelectedSet();
assertEquals(3, checkedset.size());
assertTrue(checkedset.contains(1L));
assertTrue(checkedset.contains(3L));
assertTrue(checkedset.contains(5L));
}
}
/**
* Mock Cursor for MessageList
*/
class CustomCursor extends AbstractCursor {
private final ArrayList<Long> mSortedIdList;
private final String[] mColumnNames;
public CustomCursor(ArrayList<Long> sortedIdList,
String[] columnNames,
HashMap<Long, Map<String, Object>> rows) {
mSortedIdList = sortedIdList;
mColumnNames = columnNames;
mUpdatedRows = rows;
}
@Override
public void close() {
super.close();
}
@Override
public String[] getColumnNames() {
return mColumnNames;
}
private Object getObject(int columnIndex) {
if (isClosed()) {
throw new SQLException("Already closed.");
}
int size = mSortedIdList.size();
if (mPos < 0 || mPos >= size) {
throw new CursorIndexOutOfBoundsException(mPos, size);
}
if (columnIndex < 0 || columnIndex >= getColumnCount()) {
return null;
}
return mUpdatedRows.get(mSortedIdList.get(mPos)).get(mColumnNames[columnIndex]);
}
@Override
public float getFloat(int columnIndex) {
return Float.valueOf(getObject(columnIndex).toString());
}
@Override
public double getDouble(int columnIndex) {
return Double.valueOf(getObject(columnIndex).toString());
}
@Override
public int getInt(int columnIndex) {
return Integer.valueOf(getObject(columnIndex).toString());
}
@Override
public long getLong(int columnIndex) {
return Long.valueOf(getObject(columnIndex).toString());
}
@Override
public short getShort(int columnIndex) {
return Short.valueOf(getObject(columnIndex).toString());
}
@Override
public String getString(int columnIndex) {
return String.valueOf(getObject(columnIndex));
}
@Override
public boolean isNull(int columnIndex) {
return getObject(columnIndex) == null;
}
@Override
public int getCount() {
return mSortedIdList.size();
}
}