1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.data; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1984c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chenimport android.net.Uri; 2084c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chenimport android.provider.MediaStore; 2184c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen 2290df352389eda7c964e6a43a0b752d27f16e02a7Owen Linimport com.android.gallery3d.common.ApiHelper; 2390df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.lang.ref.SoftReference; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Comparator; 27d87c8624a7ae477a6dea86d63866ade04f8d7e7cBobby Georgescuimport java.util.NoSuchElementException; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.SortedMap; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.TreeMap; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// MergeAlbum merges items from two or more MediaSets. It uses a Comparator to 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// determine the order of items. The items are assumed to be sorted in the input 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// media sets (with the same order that the Comparator uses). 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// This only handles MediaItems, not SubMediaSets. 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class LocalMergeAlbum extends MediaSet implements ContentListener { 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "LocalMergeAlbum"; 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int PAGE_SIZE = 64; 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final Comparator<MediaItem> mComparator; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final MediaSet[] mSources; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private String mName; 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private FetchCache[] mFetcher; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mSupportedOperation; 4784c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen private int mBucketId; 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // mIndex maps global position to the position of each underlying media sets. 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private TreeMap<Integer, int[]> mIndex = new TreeMap<Integer, int[]>(); 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public LocalMergeAlbum( 5384c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen Path path, Comparator<MediaItem> comparator, MediaSet[] sources, int bucketId) { 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super(path, INVALID_DATA_VERSION); 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mComparator = comparator; 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSources = sources; 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mName = sources.length == 0 ? "" : sources[0].getName(); 5884c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen mBucketId = bucketId; 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSet set : mSources) { 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin set.addContentListener(this); 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 626423defee1d8ccf4d462d40ae4f82c7d73b11ab5Bobby Georgescu reload(); 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 657eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu @Override 667eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu public boolean isCameraRoll() { 677eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu if (mSources.length == 0) return false; 687eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu for(MediaSet set : mSources) { 697eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu if (!set.isCameraRoll()) return false; 707eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu } 717eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu return true; 727eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu } 737eea4d3ac59aa88d327fc0d58f5e4052f43c54c9Bobby Georgescu 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateData() { 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<MediaSet> matches = new ArrayList<MediaSet>(); 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int supported = mSources.length == 0 ? 0 : MediaItem.SUPPORT_ALL; 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFetcher = new FetchCache[mSources.length]; 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0, n = mSources.length; i < n; ++i) { 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFetcher[i] = new FetchCache(mSources[i]); 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin supported &= mSources[i].getSupportedOperations(); 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSupportedOperation = supported; 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIndex.clear(); 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIndex.put(0, new int[mSources.length]); 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mName = mSources.length == 0 ? "" : mSources[0].getName(); 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void invalidateCache() { 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0, n = mSources.length; i < n; i++) { 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFetcher[i].invalidate(); 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIndex.clear(); 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIndex.put(0, new int[mSources.length]); 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 9784c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen public Uri getContentUri() { 9890df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin String bucketId = String.valueOf(mBucketId); 9990df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) { 10090df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin return MediaStore.Files.getContentUri("external").buildUpon() 10190df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId) 10290df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin .build(); 10390df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin } else { 10490df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin // We don't have a single URL for a merged image before ICS 10590df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin // So we used the image's URL as a substitute. 10690df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() 10790df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId) 10890df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin .build(); 10990df352389eda7c964e6a43a0b752d27f16e02a7Owen Lin } 11084c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen } 11184c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen 11284c220f10a643927c8a2126de8a755d8d7f7ec9eRay Chen @Override 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public String getName() { 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mName; 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getMediaItemCount() { 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return getTotalMediaItemCount(); 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ArrayList<MediaItem> getMediaItem(int start, int count) { 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // First find the nearest mark position <= start. 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin SortedMap<Integer, int[]> head = mIndex.headMap(start + 1); 1276423defee1d8ccf4d462d40ae4f82c7d73b11ab5Bobby Georgescu int markPos = head.lastKey(); 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int[] subPos = head.get(markPos).clone(); 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaItem[] slot = new MediaItem[mSources.length]; 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int size = mSources.length; 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // fill all slots 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < size; i++) { 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin slot[i] = mFetcher[i].getItem(subPos[i]); 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<MediaItem> result = new ArrayList<MediaItem>(); 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = markPos; i < start + count; i++) { 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int k = -1; // k points to the best slot up to now. 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int j = 0; j < size; j++) { 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (slot[j] != null) { 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (k == -1 || mComparator.compare(slot[j], slot[k]) < 0) { 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin k = j; 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // If we don't have anything, all streams are exhausted. 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (k == -1) break; 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Pick the best slot and refill it. 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin subPos[k]++; 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (i >= start) { 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin result.add(slot[k]); 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin slot[k] = mFetcher[k].getItem(subPos[k]); 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Periodically leave a mark in the index, so we can come back later. 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if ((i + 1) % PAGE_SIZE == 0) { 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIndex.put(i + 1, subPos.clone()); 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return result; 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getTotalMediaItemCount() { 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int count = 0; 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSet set : mSources) { 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin count += set.getTotalMediaItemCount(); 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return count; 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public long reload() { 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean changed = false; 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0, n = mSources.length; i < n; ++i) { 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mSources[i].reload() > mDataVersion) changed = true; 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (changed) { 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDataVersion = nextVersionNumber(); 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateData(); 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin invalidateCache(); 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mDataVersion; 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onContentDirty() { 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin notifyContentChanged(); 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getSupportedOperations() { 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mSupportedOperation; 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void delete() { 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSet set : mSources) { 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin set.delete(); 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void rotate(int degrees) { 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSet set : mSources) { 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin set.rotate(degrees); 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class FetchCache { 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private MediaSet mBaseSet; 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private SoftReference<ArrayList<MediaItem>> mCacheRef; 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mStartPos; 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public FetchCache(MediaSet baseSet) { 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mBaseSet = baseSet; 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void invalidate() { 226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCacheRef = null; 227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaItem getItem(int index) { 230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean needLoading = false; 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<MediaItem> cache = null; 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mCacheRef == null 233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin || index < mStartPos || index >= mStartPos + PAGE_SIZE) { 234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin needLoading = true; 235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cache = mCacheRef.get(); 237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (cache == null) { 238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin needLoading = true; 239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (needLoading) { 243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cache = mBaseSet.getMediaItem(index, PAGE_SIZE); 244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCacheRef = new SoftReference<ArrayList<MediaItem>>(cache); 245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mStartPos = index; 246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (index < mStartPos || index >= mStartPos + cache.size()) { 249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return cache.get(index - mStartPos); 253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean isLeafAlbum() { 258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return true; 259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 261