CursorObjectAdapter.java revision 0f1fa0dfa946ddc8afb6af26a4dd1a4d01dca10f
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 20/** 21 * Adapter implemented with a {@link Cursor}. 22 */ 23public class CursorObjectAdapter extends ObjectAdapter { 24 private static final int CACHE_SIZE = 100; 25 private Cursor mCursor; 26 private CursorMapper mMapper; 27 private final LruCache<Integer, Object> mItemCache = new LruCache<Integer, Object>(CACHE_SIZE); 28 29 public CursorObjectAdapter(PresenterSelector presenterSelector) { 30 super(presenterSelector); 31 } 32 33 public CursorObjectAdapter(Presenter presenter) { 34 super(presenter); 35 } 36 37 public CursorObjectAdapter() { 38 super(); 39 } 40 41 /** 42 * Change the underlying cursor to a new cursor. If there is 43 * an existing cursor it will be closed. 44 * 45 * @param cursor The new cursor to be used. 46 */ 47 public void changeCursor(Cursor cursor) { 48 if (cursor == mCursor) { 49 return; 50 } 51 mCursor.close(); 52 mCursor = cursor; 53 mItemCache.trimToSize(0); 54 onCursorChanged(); 55 } 56 57 /** 58 * Swap in a new Cursor, returning the old Cursor. Unlike changeCursor(Cursor), 59 * the returned old Cursor is not closed. 60 * 61 * @param cursor The new cursor to be used. 62 */ 63 public Cursor swapCursor(Cursor cursor) { 64 if (cursor == mCursor) { 65 return mCursor; 66 } 67 Cursor oldCursor = mCursor; 68 mCursor = cursor; 69 mItemCache.trimToSize(0); 70 onCursorChanged(); 71 return oldCursor; 72 } 73 74 /** 75 * Called whenever the cursor changes. 76 */ 77 protected void onCursorChanged() { 78 notifyChanged(); 79 } 80 81 /** 82 * Gets the {@link Cursor} backing the adapter. 83 */ 84 public final Cursor getCursor() { 85 return mCursor; 86 } 87 88 /** 89 * Sets the {@link CursorMapper} used to convert {@link Cursor} rows into 90 * Objects. 91 */ 92 public final void setMapper(CursorMapper mapper) { 93 mMapper = mapper; 94 } 95 96 /** 97 * Gets the {@link CursorMapper} used to convert {@link Cursor} rows into 98 * Objects. 99 */ 100 public final CursorMapper getMapper() { 101 return mMapper; 102 } 103 104 @Override 105 public int size() { 106 if (mCursor == null) { 107 return 0; 108 } 109 return mCursor.getCount(); 110 } 111 112 @Override 113 public Object get(int index) { 114 if (mCursor == null) { 115 return null; 116 } 117 if (!mCursor.moveToPosition(index)) { 118 throw new ArrayIndexOutOfBoundsException(); 119 } 120 Object item = mItemCache.get(index); 121 if (item != null) { 122 return item; 123 } 124 item = mMapper.convert(mCursor); 125 mItemCache.put(index, item); 126 return item; 127 } 128 129 /** 130 * Closes this adapter, closing the backing {@link Cursor} as well. 131 */ 132 public void close() { 133 if (mCursor != null) { 134 mCursor.close(); 135 mCursor = null; 136 } 137 } 138 139 /** 140 * Checks whether the adapter, and hence the backing {@link Cursor}, is closed. 141 */ 142 public boolean isClosed() { 143 return mCursor == null || mCursor.isClosed(); 144 } 145 146 /** 147 * Remove an item from the cache. This will force the item to be re-read 148 * from the data source the next time (@link #get(int)} is called. 149 */ 150 protected final void invalidateCache(int index) { 151 mItemCache.remove(index); 152 } 153 154 /** 155 * Remove {@code count} items starting at {@code index}. 156 */ 157 protected final void invalidateCache(int index, int count) { 158 for (int limit = count + index; index < limit; index++) { 159 invalidateCache(index); 160 } 161 } 162} 163