1 /* 2 * Copyright (C) 2015 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 package android.databinding; 17 18 import android.support.v4.util.Pools; 19 20 /** 21 * Utility class for managing ObservableList callbacks. 22 */ 23 public class ListChangeRegistry 24 extends 25 CallbackRegistry<ObservableList.OnListChangedCallback, ObservableList, 26 ListChangeRegistry.ListChanges> { 27 private static final Pools.SynchronizedPool<ListChanges> sListChanges = 28 new Pools.SynchronizedPool<>(10); 29 30 private static final int ALL = 0; 31 private static final int CHANGED = 1; 32 private static final int INSERTED = 2; 33 private static final int MOVED = 3; 34 private static final int REMOVED = 4; 35 36 private static final CallbackRegistry.NotifierCallback<ObservableList.OnListChangedCallback, 37 ObservableList, ListChanges> NOTIFIER_CALLBACK = new CallbackRegistry.NotifierCallback< 38 ObservableList.OnListChangedCallback, ObservableList, ListChanges>() { 39 @Override 40 public void onNotifyCallback(ObservableList.OnListChangedCallback callback, 41 ObservableList sender, int notificationType, ListChanges listChanges) { 42 switch (notificationType) { 43 case CHANGED: 44 callback.onItemRangeChanged(sender, listChanges.start, listChanges.count); 45 break; 46 case INSERTED: 47 callback.onItemRangeInserted(sender, listChanges.start, listChanges.count); 48 break; 49 case MOVED: 50 callback.onItemRangeMoved(sender, listChanges.start, listChanges.to, 51 listChanges.count); 52 break; 53 case REMOVED: 54 callback.onItemRangeRemoved(sender, listChanges.start, listChanges.count); 55 break; 56 default: 57 callback.onChanged(sender); 58 break; 59 } 60 } 61 }; 62 63 /** 64 * Notify registered callbacks that there was an unknown or whole-list change. 65 * 66 * @param list The list that changed. 67 */ notifyChanged(ObservableList list)68 public void notifyChanged(ObservableList list) { 69 notifyCallbacks(list, ALL, null); 70 } 71 72 /** 73 * Notify registered callbacks that some elements have changed. 74 * 75 * @param list The list that changed. 76 * @param start The index of the first changed element. 77 * @param count The number of changed elements. 78 */ notifyChanged(ObservableList list, int start, int count)79 public void notifyChanged(ObservableList list, int start, int count) { 80 ListChanges listChanges = acquire(start, 0, count); 81 notifyCallbacks(list, CHANGED, listChanges); 82 } 83 84 /** 85 * Notify registered callbacks that elements were inserted. 86 * 87 * @param list The list that changed. 88 * @param start The index where the elements were inserted. 89 * @param count The number of elements that were inserted. 90 */ notifyInserted(ObservableList list, int start, int count)91 public void notifyInserted(ObservableList list, int start, int count) { 92 ListChanges listChanges = acquire(start, 0, count); 93 notifyCallbacks(list, INSERTED, listChanges); 94 } 95 96 /** 97 * Notify registered callbacks that elements were moved. 98 * 99 * @param list The list that changed. 100 * @param from The index of the first element moved. 101 * @param to The index of where the element was moved to. 102 * @param count The number of elements moved. 103 */ notifyMoved(ObservableList list, int from, int to, int count)104 public void notifyMoved(ObservableList list, int from, int to, int count) { 105 ListChanges listChanges = acquire(from, to, count); 106 notifyCallbacks(list, MOVED, listChanges); 107 } 108 109 /** 110 * Notify registered callbacks that elements were deleted. 111 * 112 * @param list The list that changed. 113 * @param start The index of the first element to be removed. 114 * @param count The number of elements removed. 115 */ notifyRemoved(ObservableList list, int start, int count)116 public void notifyRemoved(ObservableList list, int start, int count) { 117 ListChanges listChanges = acquire(start, 0, count); 118 notifyCallbacks(list, REMOVED, listChanges); 119 } 120 acquire(int start, int to, int count)121 private static ListChanges acquire(int start, int to, int count) { 122 ListChanges listChanges = sListChanges.acquire(); 123 if (listChanges == null) { 124 listChanges = new ListChanges(); 125 } 126 listChanges.start = start; 127 listChanges.to = to; 128 listChanges.count = count; 129 return listChanges; 130 } 131 132 @Override notifyCallbacks(ObservableList sender, int notificationType, ListChanges listChanges)133 public synchronized void notifyCallbacks(ObservableList sender, int notificationType, 134 ListChanges listChanges) { 135 super.notifyCallbacks(sender, notificationType, listChanges); 136 if (listChanges != null) { 137 sListChanges.release(listChanges); 138 } 139 } 140 ListChangeRegistry()141 public ListChangeRegistry() { 142 super(NOTIFIER_CALLBACK); 143 } 144 145 static class ListChanges { 146 public int start; 147 public int count; 148 public int to; 149 } 150 } 151