CursorObjectAdapter.java revision 2eaaad9c189f1ae42bf6c382a30ccab455030e54
120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn/* 220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Copyright (C) 2014 The Android Open Source Project 320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * in compliance with the License. You may obtain a copy of the License at 620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * http://www.apache.org/licenses/LICENSE-2.0 820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Unless required by applicable law or agreed to in writing, software distributed under the License 1020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * or implied. See the License for the specific language governing permissions and limitations under 1220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * the License. 1320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 1420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournpackage android.support.v17.leanback.widget; 1520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 1620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournimport android.database.Cursor; 1720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournimport android.support.v17.leanback.database.CursorMapper; 1820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournimport android.util.LruCache; 1920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 2020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn/** 2120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Adapter implemented with a {@link Cursor}. 2220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 2320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournpublic class CursorObjectAdapter extends ObjectAdapter { 2420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn private static final int CACHE_SIZE = 100; 250f1fa0dfa946ddc8afb6af26a4dd1a4d01dca10fDake Gu private Cursor mCursor; 260f1fa0dfa946ddc8afb6af26a4dd1a4d01dca10fDake Gu private CursorMapper mMapper; 270f1fa0dfa946ddc8afb6af26a4dd1a4d01dca10fDake Gu private final LruCache<Integer, Object> mItemCache = new LruCache<Integer, Object>(CACHE_SIZE); 2820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 2920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public CursorObjectAdapter(PresenterSelector presenterSelector) { 3020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn super(presenterSelector); 3120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 3220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 3320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public CursorObjectAdapter(Presenter presenter) { 3420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn super(presenter); 3520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 3620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 3720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public CursorObjectAdapter() { 3820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn super(); 3920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 4020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 4120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 4220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Change the underlying cursor to a new cursor. If there is 4320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * an existing cursor it will be closed. 4420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 4520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * @param cursor The new cursor to be used. 4620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 4720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public void changeCursor(Cursor cursor) { 4820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn if (cursor == mCursor) { 4920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return; 5020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 512eaaad9c189f1ae42bf6c382a30ccab455030e54Andrew Wilson if (mCursor != null) { 522eaaad9c189f1ae42bf6c382a30ccab455030e54Andrew Wilson mCursor.close(); 532eaaad9c189f1ae42bf6c382a30ccab455030e54Andrew Wilson } 5420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mCursor = cursor; 5520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mItemCache.trimToSize(0); 5620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn onCursorChanged(); 5720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 5820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 5920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 6020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Swap in a new Cursor, returning the old Cursor. Unlike changeCursor(Cursor), 6120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * the returned old Cursor is not closed. 6220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 6320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * @param cursor The new cursor to be used. 6420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 6520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public Cursor swapCursor(Cursor cursor) { 6620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn if (cursor == mCursor) { 6720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return mCursor; 6820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 6920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn Cursor oldCursor = mCursor; 7020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mCursor = cursor; 7120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mItemCache.trimToSize(0); 7220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn onCursorChanged(); 7320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return oldCursor; 7420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 7520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 7620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 7720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Called whenever the cursor changes. 7820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 7920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn protected void onCursorChanged() { 8020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn notifyChanged(); 8120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 8220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 8320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 8420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Gets the {@link Cursor} backing the adapter. 8520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 860f1fa0dfa946ddc8afb6af26a4dd1a4d01dca10fDake Gu public final Cursor getCursor() { 8720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return mCursor; 8820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 8920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 9020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 9120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Sets the {@link CursorMapper} used to convert {@link Cursor} rows into 9220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Objects. 9320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 940f1fa0dfa946ddc8afb6af26a4dd1a4d01dca10fDake Gu public final void setMapper(CursorMapper mapper) { 9520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mMapper = mapper; 9620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 9720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 9820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 9920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Gets the {@link CursorMapper} used to convert {@link Cursor} rows into 10020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Objects. 10120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 1020f1fa0dfa946ddc8afb6af26a4dd1a4d01dca10fDake Gu public final CursorMapper getMapper() { 10320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return mMapper; 10420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 10520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 10620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn @Override 10720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public int size() { 10820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn if (mCursor == null) { 10920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return 0; 11020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 11120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return mCursor.getCount(); 11220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 11320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 11420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn @Override 11520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public Object get(int index) { 11620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn if (mCursor == null) { 11720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return null; 11820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 11920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn if (!mCursor.moveToPosition(index)) { 12020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn throw new ArrayIndexOutOfBoundsException(); 12120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 12220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn Object item = mItemCache.get(index); 12320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn if (item != null) { 12420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return item; 12520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 12620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn item = mMapper.convert(mCursor); 12720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mItemCache.put(index, item); 12820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return item; 12920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 13020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 13120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 13220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Closes this adapter, closing the backing {@link Cursor} as well. 13320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 13420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public void close() { 13520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn if (mCursor != null) { 13620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mCursor.close(); 13720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn mCursor = null; 13820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 13920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 14020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 14120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 14220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Checks whether the adapter, and hence the backing {@link Cursor}, is closed. 14320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 14420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public boolean isClosed() { 14520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn return mCursor == null || mCursor.isClosed(); 14620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 147c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson 148c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson /** 149c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson * Remove an item from the cache. This will force the item to be re-read 150c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson * from the data source the next time (@link #get(int)} is called. 151c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson */ 152c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson protected final void invalidateCache(int index) { 153c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson mItemCache.remove(index); 154c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson } 155c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson 156c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson /** 157c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson * Remove {@code count} items starting at {@code index}. 158c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson */ 159c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson protected final void invalidateCache(int index, int count) { 160c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson for (int limit = count + index; index < limit; index++) { 161c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson invalidateCache(index); 162c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson } 163c251a00602f6872d07e5b464ce7c67e78696438eJustin Mattson } 16420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn} 165