1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.recyclerview.widget; 18 19 import androidx.collection.LongSparseArray; 20 21 import org.jspecify.annotations.NonNull; 22 23 /** 24 * Used by {@link ConcatAdapter} to isolate item ids between nested adapters, if necessary. 25 */ 26 interface StableIdStorage { createStableIdLookup()27 @NonNull StableIdLookup createStableIdLookup(); 28 29 /** 30 * Interface that provides {@link NestedAdapterWrapper}s a way to map their local stable ids 31 * into global stable ids, based on the configuration of the {@link ConcatAdapter}. 32 */ 33 interface StableIdLookup { localToGlobal(long localId)34 long localToGlobal(long localId); 35 } 36 37 /** 38 * Returns {@link RecyclerView#NO_ID} for all positions. In other words, stable ids are not 39 * supported. 40 */ 41 class NoStableIdStorage implements StableIdStorage { 42 private final StableIdLookup mNoIdLookup = new StableIdLookup() { 43 @Override 44 public long localToGlobal(long localId) { 45 return RecyclerView.NO_ID; 46 } 47 }; 48 49 @Override createStableIdLookup()50 public @NonNull StableIdLookup createStableIdLookup() { 51 return mNoIdLookup; 52 } 53 } 54 55 /** 56 * A pass-through implementation that reports the stable id in sub adapters as is. 57 */ 58 class SharedPoolStableIdStorage implements StableIdStorage { 59 private final StableIdLookup mSameIdLookup = new StableIdLookup() { 60 @Override 61 public long localToGlobal(long localId) { 62 return localId; 63 } 64 }; 65 66 @Override createStableIdLookup()67 public @NonNull StableIdLookup createStableIdLookup() { 68 return mSameIdLookup; 69 } 70 } 71 72 /** 73 * An isolating implementation that ensures the stable ids among adapters do not conflict with 74 * each-other. It keeps a mapping for each adapter from its local stable ids to a global domain 75 * and always replaces the local id w/ a globally available ID to be consistent. 76 */ 77 class IsolatedStableIdStorage implements StableIdStorage { 78 long mNextStableId = 0; 79 obtainId()80 long obtainId() { 81 return mNextStableId++; 82 } 83 84 @Override createStableIdLookup()85 public @NonNull StableIdLookup createStableIdLookup() { 86 return new WrapperStableIdLookup(); 87 } 88 89 class WrapperStableIdLookup implements StableIdLookup { 90 private final LongSparseArray<Long> mLocalToGlobalLookup = new LongSparseArray<>(); 91 92 @Override localToGlobal(long localId)93 public long localToGlobal(long localId) { 94 Long globalId = mLocalToGlobalLookup.get(localId); 95 if (globalId == null) { 96 globalId = obtainId(); 97 mLocalToGlobalLookup.put(localId, globalId); 98 } 99 return globalId; 100 } 101 } 102 } 103 } 104