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