CursorObjectAdapter.java revision 8b068ddbbf22a246eab49ec25a2f7c3abfbdca51
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14package android.support.v17.leanback.widget; 15 16import android.database.Cursor; 17import android.support.v17.leanback.database.CursorMapper; 18import android.util.LruCache; 19 20import java.util.Map; 21 22/** 23 * Adapter implemented with a {@link Cursor}. 24 */ 25public class CursorObjectAdapter extends ObjectAdapter { 26 private static final int CACHE_SIZE = 100; 27 protected Cursor mCursor; 28 protected CursorMapper mMapper; 29 private final LruCache<Integer, Object> mItemCache = new LruCache(CACHE_SIZE); 30 31 public CursorObjectAdapter(PresenterSelector presenterSelector) { 32 super(presenterSelector); 33 } 34 35 public CursorObjectAdapter(Presenter presenter) { 36 super(presenter); 37 } 38 39 public CursorObjectAdapter() { 40 super(); 41 } 42 43 /** 44 * Change the underlying cursor to a new cursor. If there is 45 * an existing cursor it will be closed. 46 * 47 * @param cursor The new cursor to be used. 48 */ 49 public void changeCursor(Cursor cursor) { 50 if (cursor == mCursor) { 51 return; 52 } 53 mCursor.close(); 54 mCursor = cursor; 55 mItemCache.trimToSize(0); 56 onCursorChanged(); 57 } 58 59 /** 60 * Swap in a new Cursor, returning the old Cursor. Unlike changeCursor(Cursor), 61 * the returned old Cursor is not closed. 62 * 63 * @param cursor The new cursor to be used. 64 */ 65 public Cursor swapCursor(Cursor cursor) { 66 if (cursor == mCursor) { 67 return mCursor; 68 } 69 Cursor oldCursor = mCursor; 70 mCursor = cursor; 71 mItemCache.trimToSize(0); 72 onCursorChanged(); 73 return oldCursor; 74 } 75 76 /** 77 * Called whenever the cursor changes. 78 */ 79 protected void onCursorChanged() { 80 notifyChanged(); 81 } 82 83 /** 84 * Gets the {@link Cursor} backing the adapter. 85 */ 86 public Cursor getCursor() { 87 return mCursor; 88 } 89 90 /** 91 * Sets the {@link CursorMapper} used to convert {@link Cursor} rows into 92 * Objects. 93 */ 94 public void setMapper(CursorMapper mapper) { 95 mMapper = mapper; 96 } 97 98 /** 99 * Gets the {@link CursorMapper} used to convert {@link Cursor} rows into 100 * Objects. 101 */ 102 public CursorMapper getMapper() { 103 return mMapper; 104 } 105 106 @Override 107 public int size() { 108 if (mCursor == null) { 109 return 0; 110 } 111 return mCursor.getCount(); 112 } 113 114 @Override 115 public Object get(int index) { 116 if (mCursor == null) { 117 return null; 118 } 119 if (!mCursor.moveToPosition(index)) { 120 throw new ArrayIndexOutOfBoundsException(); 121 } 122 Object item = mItemCache.get(index); 123 if (item != null) { 124 return item; 125 } 126 item = mMapper.convert(mCursor); 127 mItemCache.put(index, item); 128 return item; 129 } 130 131 /** 132 * Closes this adapter, closing the backing {@link Cursor} as well. 133 */ 134 public void close() { 135 if (mCursor != null) { 136 mCursor.close(); 137 mCursor = null; 138 } 139 } 140 141 /** 142 * Checks whether the adapter, and hence the backing {@link Cursor}, is closed. 143 */ 144 public boolean isClosed() { 145 return mCursor == null || mCursor.isClosed(); 146 } 147 148 /** 149 * Remove an item from the cache. This will force the item to be re-read 150 * from the data source the next time (@link #get(int)} is called. 151 */ 152 protected final void invalidateCache(int index) { 153 mItemCache.remove(index); 154 } 155 156 /** 157 * Remove {@code count} items starting at {@code index}. 158 */ 159 protected final void invalidateCache(int index, int count) { 160 for (int limit = count + index; index < limit; index++) { 161 invalidateCache(index); 162 } 163 } 164} 165