19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Activity; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.DataSetObserver; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An adapter that exposes data from a series of {@link Cursor}s to an 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView} widget. The top-level {@link Cursor} (that is 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * given in the constructor) exposes the groups, while subsequent {@link Cursor}s 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returned from {@link #getChildrenCursor(Cursor)} expose children within a 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * particular group. The Cursors must include a column named "_id" or this class 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will not work. 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class CursorTreeAdapter extends BaseExpandableListAdapter implements Filterable, 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CursorFilter.CursorFilterClient { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Handler mHandler; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAutoRequery; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The cursor helper that is used to get the groups */ 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MyCursorHelper mGroupCursorHelper; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The map of a group position to the group's children cursor helper (the 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursor helper that is used to get the children for that group) 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SparseArray<MyCursorHelper> mChildrenCursorHelpers; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Filter related 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CursorFilter mCursorFilter; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FilterQueryProvider mFilterQueryProvider; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor. The adapter will call {@link Cursor#requery()} on the cursor whenever 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it changes so that the most recent data is always displayed. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursor The cursor from which to get the data for the groups. 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CursorTreeAdapter(Cursor cursor, Context context) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(cursor, context, true); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor. 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursor The cursor from which to get the data for the groups. 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context The context 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param autoRequery If true the adapter will call {@link Cursor#requery()} 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * on the cursor whenever it changes so the most recent data is 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * always displayed. 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CursorTreeAdapter(Cursor cursor, Context context, boolean autoRequery) { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(cursor, context, autoRequery); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void init(Cursor cursor, Context context, boolean autoRequery) { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler = new Handler(); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAutoRequery = autoRequery; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupCursorHelper = new MyCursorHelper(cursor); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildrenCursorHelpers = new SparseArray<MyCursorHelper>(); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the cursor helper for the children in the given group. 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group whose children will be returned 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param requestCursor Whether to request a Cursor via 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getChildrenCursor(Cursor)} (true), or to assume a call 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to {@link #setChildrenCursor(int, Cursor)} will happen shortly 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (false). 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cursor helper for the children of the given group 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized MyCursorHelper getChildrenCursorHelper(int groupPosition, boolean requestCursor) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MyCursorHelper cursorHelper = mChildrenCursorHelpers.get(groupPosition); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursorHelper == null) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGroupCursorHelper.moveTo(groupPosition) == null) return null; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Cursor cursor = getChildrenCursor(mGroupCursorHelper.getCursor()); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursorHelper = new MyCursorHelper(cursor); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildrenCursorHelpers.put(groupPosition, cursorHelper); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cursorHelper; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the Cursor for the children at the given group. Subclasses must 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implement this method to return the children data for a particular group. 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If you want to asynchronously query a provider to prevent blocking the 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * UI, it is possible to return null and at a later time call 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setChildrenCursor(int, Cursor)}. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It is your responsibility to manage this Cursor through the Activity 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * lifecycle. It is a good idea to use {@link Activity#managedQuery} which 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will handle this for you. In some situations, the adapter will deactivate 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the Cursor on its own, but this will not always be the case, so please 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ensure the Cursor is properly managed. 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupCursor The cursor pointing to the group whose children cursor 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should be returned 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cursor for the children of a particular group, or null. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project abstract protected Cursor getChildrenCursor(Cursor groupCursor); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the group Cursor. 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1364b08d3e4372d994ac5c5a97d8da528e5d682e732Jason Parks * @param cursor The Cursor to set for the group. If there is an existing cursor 1374b08d3e4372d994ac5c5a97d8da528e5d682e732Jason Parks * it will be closed. 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGroupCursor(Cursor cursor) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupCursorHelper.changeCursor(cursor, false); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1444b08d3e4372d994ac5c5a97d8da528e5d682e732Jason Parks * Sets the children Cursor for a particular group. If there is an existing cursor 1454b08d3e4372d994ac5c5a97d8da528e5d682e732Jason Parks * it will be closed. 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is useful when asynchronously querying to prevent blocking the UI. 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group whose children are being set via this Cursor. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenCursor The Cursor that contains the children of the group. 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChildrenCursor(int groupPosition, Cursor childrenCursor) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't request a cursor from the subclass, instead we will be setting 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the cursor ourselves. 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MyCursorHelper childrenCursorHelper = getChildrenCursorHelper(groupPosition, false); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't release any cursor since we know exactly what data is changing 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (this cursor, which is still valid). 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childrenCursorHelper.changeCursor(childrenCursor, false); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor getChild(int groupPosition, int childPosition) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Return this group's children Cursor pointing to the particular child 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getChildrenCursorHelper(groupPosition, true).moveTo(childPosition); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getChildId(int groupPosition, int childPosition) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getChildrenCursorHelper(groupPosition, true).getId(childPosition); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChildrenCount(int groupPosition) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MyCursorHelper helper = getChildrenCursorHelper(groupPosition, true); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mGroupCursorHelper.isValid() && helper != null) ? helper.getCount() : 0; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor getGroup(int groupPosition) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Return the group Cursor pointing to the given group 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGroupCursorHelper.moveTo(groupPosition); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getGroupCount() { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGroupCursorHelper.getCount(); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getGroupId(int groupPosition) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGroupCursorHelper.getId(groupPosition); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View getGroupView(int groupPosition, boolean isExpanded, View convertView, 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup parent) { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor cursor = mGroupCursorHelper.moveTo(groupPosition); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursor == null) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("this should only be called when the cursor is valid"); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View v; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (convertView == null) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = newGroupView(mContext, cursor, isExpanded, parent); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = convertView; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bindGroupView(v, mContext, cursor, isExpanded); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Makes a new group view to hold the group data pointed to by cursor. 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context Interface to application's global information 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursor The group cursor from which to get the data. The cursor is 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * already moved to the correct position. 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isExpanded Whether the group is expanded. 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent The parent to which the new view is attached to 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The newly created view. 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected abstract View newGroupView(Context context, Cursor cursor, boolean isExpanded, 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup parent); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bind an existing view to the group data pointed to by cursor. 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view Existing view, returned earlier by newGroupView. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context Interface to application's global information 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursor The cursor from which to get the data. The cursor is 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * already moved to the correct position. 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isExpanded Whether the group is expanded. 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected abstract void bindGroupView(View view, Context context, Cursor cursor, 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isExpanded); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View getChildView(int groupPosition, int childPosition, boolean isLastChild, 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View convertView, ViewGroup parent) { 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MyCursorHelper cursorHelper = getChildrenCursorHelper(groupPosition, true); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor cursor = cursorHelper.moveTo(childPosition); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursor == null) { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("this should only be called when the cursor is valid"); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View v; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (convertView == null) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = newChildView(mContext, cursor, isLastChild, parent); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = convertView; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bindChildView(v, mContext, cursor, isLastChild); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Makes a new child view to hold the data pointed to by cursor. 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context Interface to application's global information 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursor The cursor from which to get the data. The cursor is 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * already moved to the correct position. 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isLastChild Whether the child is the last child within its group. 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent The parent to which the new view is attached to 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the newly created view. 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected abstract View newChildView(Context context, Cursor cursor, boolean isLastChild, 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup parent); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bind an existing view to the child data pointed to by cursor 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view Existing view, returned earlier by newChildView 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context Interface to application's global information 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursor The cursor from which to get the data. The cursor is 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * already moved to the correct position. 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isLastChild Whether the child is the last child within its group. 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected abstract void bindChildView(View view, Context context, Cursor cursor, 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isLastChild); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isChildSelectable(int groupPosition, int childPosition) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean hasStableIds() { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private synchronized void releaseCursorHelpers() { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int pos = mChildrenCursorHelpers.size() - 1; pos >= 0; pos--) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildrenCursorHelpers.valueAt(pos).deactivate(); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildrenCursorHelpers.clear(); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notifyDataSetChanged() { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyDataSetChanged(true); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notifies a data set change, but with the option of not releasing any 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cached cursors. 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param releaseCursors Whether to release and deactivate any cached 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursors. 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notifyDataSetChanged(boolean releaseCursors) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (releaseCursors) { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project releaseCursorHelpers(); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.notifyDataSetChanged(); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notifyDataSetInvalidated() { 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project releaseCursorHelpers(); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.notifyDataSetInvalidated(); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onGroupCollapsed(int groupPosition) { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project deactivateChildrenCursorHelper(groupPosition); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Deactivates the Cursor and removes the helper from cache. 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group whose children Cursor and helper should be 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * deactivated. 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized void deactivateChildrenCursorHelper(int groupPosition) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MyCursorHelper cursorHelper = getChildrenCursorHelper(groupPosition, true); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildrenCursorHelpers.remove(groupPosition); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursorHelper.deactivate(); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see CursorAdapter#convertToString(Cursor) 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String convertToString(Cursor cursor) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cursor == null ? "" : cursor.toString(); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see CursorAdapter#runQueryOnBackgroundThread(CharSequence) 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor runQueryOnBackgroundThread(CharSequence constraint) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFilterQueryProvider != null) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFilterQueryProvider.runQuery(constraint); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGroupCursorHelper.getCursor(); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Filter getFilter() { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCursorFilter == null) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursorFilter = new CursorFilter(this); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCursorFilter; 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see CursorAdapter#getFilterQueryProvider() 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FilterQueryProvider getFilterQueryProvider() { 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFilterQueryProvider; 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see CursorAdapter#setFilterQueryProvider(FilterQueryProvider) 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) { 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFilterQueryProvider = filterQueryProvider; 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see CursorAdapter#changeCursor(Cursor) 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void changeCursor(Cursor cursor) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupCursorHelper.changeCursor(cursor, true); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see CursorAdapter#getCursor() 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor getCursor() { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGroupCursorHelper.getCursor(); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper class for Cursor management: 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Data validity 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Funneling the content and data set observers from a Cursor to a 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * single data set observer for widgets 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> ID from the Cursor for use in adapter IDs 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Swapping cursors but maintaining other metadata 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class MyCursorHelper { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Cursor mCursor; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mDataValid; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRowIDColumn; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MyContentObserver mContentObserver; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MyDataSetObserver mDataSetObserver; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MyCursorHelper(Cursor cursor) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean cursorPresent = cursor != null; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursor = cursor; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataValid = cursorPresent; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRowIDColumn = cursorPresent ? cursor.getColumnIndex("_id") : -1; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContentObserver = new MyContentObserver(); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataSetObserver = new MyDataSetObserver(); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursorPresent) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursor.registerContentObserver(mContentObserver); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursor.registerDataSetObserver(mDataSetObserver); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor getCursor() { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCursor; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int getCount() { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDataValid && mCursor != null) { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCursor.getCount(); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long getId(int position) { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDataValid && mCursor != null) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCursor.moveToPosition(position)) { 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCursor.getLong(mRowIDColumn); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor moveTo(int position) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDataValid && (mCursor != null) && mCursor.moveToPosition(position)) { 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCursor; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void changeCursor(Cursor cursor, boolean releaseCursors) { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursor == mCursor) return; 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project deactivate(); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursor = cursor; 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursor != null) { 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursor.registerContentObserver(mContentObserver); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursor.registerDataSetObserver(mDataSetObserver); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRowIDColumn = cursor.getColumnIndex("_id"); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataValid = true; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // notify the observers about the new cursor 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyDataSetChanged(releaseCursors); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRowIDColumn = -1; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataValid = false; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // notify the observers about the lack of a data set 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyDataSetInvalidated(); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void deactivate() { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCursor == null) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursor.unregisterContentObserver(mContentObserver); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursor.unregisterDataSetObserver(mDataSetObserver); 4804b08d3e4372d994ac5c5a97d8da528e5d682e732Jason Parks mCursor.close(); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursor = null; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isValid() { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDataValid && mCursor != null; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class MyContentObserver extends ContentObserver { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MyContentObserver() { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(mHandler); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean deliverSelfNotifications() { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onChange(boolean selfChange) { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAutoRequery && mCursor != null) { 50143a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato if (false) Log.v("Cursor", "Auto requerying " + mCursor + 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " due to update"); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataValid = mCursor.requery(); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class MyDataSetObserver extends DataSetObserver { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onChanged() { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataValid = true; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyDataSetChanged(); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onInvalidated() { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataValid = false; 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyDataSetInvalidated(); 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 523