1 /*
2  * Copyright 2018 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 org.jspecify.annotations.NonNull;
20 
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.concurrent.CountDownLatch;
24 import java.util.concurrent.TimeUnit;
25 
26 public class LoggingItemAnimator extends DefaultItemAnimator {
27 
28     final ArrayList<RecyclerView.ViewHolder> mAddVHs = new ArrayList<RecyclerView.ViewHolder>();
29 
30     final ArrayList<RecyclerView.ViewHolder> mRemoveVHs = new ArrayList<RecyclerView.ViewHolder>();
31 
32     final ArrayList<RecyclerView.ViewHolder> mMoveVHs = new ArrayList<RecyclerView.ViewHolder>();
33 
34     final ArrayList<RecyclerView.ViewHolder> mChangeOldVHs = new ArrayList<RecyclerView.ViewHolder>();
35 
36     final ArrayList<RecyclerView.ViewHolder> mChangeNewVHs = new ArrayList<RecyclerView.ViewHolder>();
37 
38     List<BaseRecyclerViewAnimationsTest.AnimateAppearance> mAnimateAppearanceList = new ArrayList<>();
39     List<BaseRecyclerViewAnimationsTest.AnimateDisappearance> mAnimateDisappearanceList = new ArrayList<>();
40     List<BaseRecyclerViewAnimationsTest.AnimatePersistence> mAnimatePersistenceList = new ArrayList<>();
41     List<BaseRecyclerViewAnimationsTest.AnimateChange> mAnimateChangeList = new ArrayList<>();
42 
43     CountDownLatch mWaitForPendingAnimations;
44 
contains(RecyclerView.ViewHolder viewHolder, List<? extends BaseRecyclerViewAnimationsTest.AnimateLogBase> list)45     public boolean contains(RecyclerView.ViewHolder viewHolder,
46             List<? extends BaseRecyclerViewAnimationsTest.AnimateLogBase> list) {
47         for (BaseRecyclerViewAnimationsTest.AnimateLogBase log : list) {
48             if (log.viewHolder == viewHolder) {
49                 return true;
50             }
51             if (log instanceof BaseRecyclerViewAnimationsTest.AnimateChange) {
52                 if (((BaseRecyclerViewAnimationsTest.AnimateChange) log).newHolder == viewHolder) {
53                     return true;
54                 }
55             }
56         }
57         return false;
58     }
59 
60     @Override
recordPreLayoutInformation(RecyclerView.@onNull State state, RecyclerView.@NonNull ViewHolder viewHolder, @AdapterChanges int changeFlags, @NonNull List<Object> payloads)61     public @NonNull ItemHolderInfo recordPreLayoutInformation(RecyclerView.@NonNull State state,
62             RecyclerView.@NonNull ViewHolder viewHolder,
63             @AdapterChanges int changeFlags, @NonNull List<Object> payloads) {
64         BaseRecyclerViewAnimationsTest.LoggingInfo
65                 loggingInfo = new BaseRecyclerViewAnimationsTest.LoggingInfo(viewHolder, changeFlags, payloads);
66         return loggingInfo;
67     }
68 
69     @Override
recordPostLayoutInformation(RecyclerView.@onNull State state, RecyclerView.@NonNull ViewHolder viewHolder)70     public @NonNull ItemHolderInfo recordPostLayoutInformation(RecyclerView.@NonNull State state,
71             RecyclerView.@NonNull ViewHolder viewHolder) {
72         BaseRecyclerViewAnimationsTest.LoggingInfo
73                 loggingInfo = new BaseRecyclerViewAnimationsTest.LoggingInfo(viewHolder, 0, null);
74         return loggingInfo;
75     }
76 
77 
78     @Override
animateDisappearance(RecyclerView.@onNull ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, ItemHolderInfo postLayoutInfo)79     public boolean animateDisappearance(RecyclerView.@NonNull ViewHolder viewHolder,
80             @NonNull ItemHolderInfo preLayoutInfo, ItemHolderInfo postLayoutInfo) {
81         mAnimateDisappearanceList
82                 .add(new BaseRecyclerViewAnimationsTest.AnimateDisappearance(viewHolder,
83                         (BaseRecyclerViewAnimationsTest.LoggingInfo) preLayoutInfo,
84                         (BaseRecyclerViewAnimationsTest.LoggingInfo) postLayoutInfo));
85         return super.animateDisappearance(viewHolder, preLayoutInfo, postLayoutInfo);
86     }
87 
88     @Override
animateAppearance(RecyclerView.@onNull ViewHolder viewHolder, ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo)89     public boolean animateAppearance(RecyclerView.@NonNull ViewHolder viewHolder,
90             ItemHolderInfo preLayoutInfo,
91             @NonNull ItemHolderInfo postLayoutInfo) {
92         mAnimateAppearanceList
93                 .add(new BaseRecyclerViewAnimationsTest.AnimateAppearance(viewHolder,
94                         (BaseRecyclerViewAnimationsTest.LoggingInfo) preLayoutInfo,
95                         (BaseRecyclerViewAnimationsTest.LoggingInfo) postLayoutInfo));
96         return super.animateAppearance(viewHolder, preLayoutInfo, postLayoutInfo);
97     }
98 
99     @Override
animatePersistence(RecyclerView.@onNull ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo)100     public boolean animatePersistence(RecyclerView.@NonNull ViewHolder viewHolder,
101             @NonNull ItemHolderInfo preLayoutInfo,
102             @NonNull ItemHolderInfo postLayoutInfo) {
103         mAnimatePersistenceList
104                 .add(new BaseRecyclerViewAnimationsTest.AnimatePersistence(viewHolder,
105                         (BaseRecyclerViewAnimationsTest.LoggingInfo) preLayoutInfo,
106                         (BaseRecyclerViewAnimationsTest.LoggingInfo) postLayoutInfo));
107         return super.animatePersistence(viewHolder, preLayoutInfo, postLayoutInfo);
108     }
109 
110     @Override
animateChange(RecyclerView.@onNull ViewHolder oldHolder, RecyclerView.@NonNull ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo)111     public boolean animateChange(RecyclerView.@NonNull ViewHolder oldHolder,
112             RecyclerView.@NonNull ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo,
113             @NonNull ItemHolderInfo postLayoutInfo) {
114         mAnimateChangeList
115                 .add(new BaseRecyclerViewAnimationsTest.AnimateChange(oldHolder, newHolder,
116                         (BaseRecyclerViewAnimationsTest.LoggingInfo) preLayoutInfo,
117                         (BaseRecyclerViewAnimationsTest.LoggingInfo) postLayoutInfo));
118         return super.animateChange(oldHolder, newHolder, preLayoutInfo, postLayoutInfo);
119     }
120 
121     @Override
runPendingAnimations()122     public void runPendingAnimations() {
123         if (mWaitForPendingAnimations != null) {
124             mWaitForPendingAnimations.countDown();
125         }
126         super.runPendingAnimations();
127     }
128 
expectRunPendingAnimationsCall(int count)129     public void expectRunPendingAnimationsCall(int count) {
130         mWaitForPendingAnimations = new CountDownLatch(count);
131     }
132 
waitForPendingAnimationsCall(int seconds)133     public void waitForPendingAnimationsCall(int seconds) throws InterruptedException {
134         mWaitForPendingAnimations.await(seconds, TimeUnit.SECONDS);
135     }
136 
137     @Override
animateAdd(RecyclerView.@onNull ViewHolder holder)138     public boolean animateAdd(RecyclerView.@NonNull ViewHolder holder) {
139         mAddVHs.add(holder);
140         return super.animateAdd(holder);
141     }
142 
143     @Override
animateRemove(RecyclerView.@onNull ViewHolder holder)144     public boolean animateRemove(RecyclerView.@NonNull ViewHolder holder) {
145         mRemoveVHs.add(holder);
146         return super.animateRemove(holder);
147     }
148 
149     @Override
animateMove(RecyclerView.@onNull ViewHolder holder, int fromX, int fromY, int toX, int toY)150     public boolean animateMove(RecyclerView.@NonNull ViewHolder holder, int fromX, int fromY,
151             int toX, int toY) {
152         mMoveVHs.add(holder);
153         return super.animateMove(holder, fromX, fromY, toX, toY);
154     }
155 
156     @Override
animateChange(RecyclerView.@onNull ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop)157     public boolean animateChange(RecyclerView.@NonNull ViewHolder oldHolder,
158             RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) {
159         if (oldHolder != null) {
160             mChangeOldVHs.add(oldHolder);
161         }
162         if (newHolder != null) {
163             mChangeNewVHs.add(newHolder);
164         }
165         return super.animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, toTop);
166     }
167 
reset()168     public void reset() {
169         mAddVHs.clear();
170         mRemoveVHs.clear();
171         mMoveVHs.clear();
172         mChangeOldVHs.clear();
173         mChangeNewVHs.clear();
174         mAnimateChangeList.clear();
175         mAnimatePersistenceList.clear();
176         mAnimateAppearanceList.clear();
177         mAnimateDisappearanceList.clear();
178     }
179 }