1 /*
2  * Copyright (C) 2023 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 com.chassis.car.ui.plugin.recyclerview;
18 
19 import android.content.Context;
20 import android.view.View;
21 import android.view.ViewGroup;
22 import android.widget.FrameLayout;
23 
24 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable;
26 import androidx.recyclerview.widget.RecyclerView;
27 
28 import com.android.car.ui.plugin.oemapis.recyclerview.AdapterDataObserverOEMV1;
29 import com.android.car.ui.plugin.oemapis.recyclerview.AdapterOEMV1;
30 import com.android.car.ui.plugin.oemapis.recyclerview.RecyclerViewOEMV1;
31 import com.android.car.ui.plugin.oemapis.recyclerview.ViewHolderOEMV1;
32 import com.android.car.ui.recyclerview.CarUiListItemAdapter;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 /**
38  * Adapts a {@link CarUiListItemAdapter} into a {@link AdapterOEMV1}
39  */
40 public class CarListItemAdapterAdapterProxy implements
41         AdapterOEMV1<CarListItemAdapterAdapterProxy.ViewHolderWrapper> {
42 
43     private final CarUiListItemAdapter mDelegateAdapter;
44     private final Context mPluginContext;
45 
46 
CarListItemAdapterAdapterProxy(CarUiListItemAdapter carUiListItemAdapter, Context pluginContext)47     public CarListItemAdapterAdapterProxy(CarUiListItemAdapter carUiListItemAdapter,
48             Context pluginContext) {
49         mPluginContext = pluginContext;
50         mDelegateAdapter = carUiListItemAdapter;
51     }
52 
53     @Override
getItemCount()54     public int getItemCount() {
55         return mDelegateAdapter.getItemCount();
56     }
57 
58     @Override
getItemId(int position)59     public long getItemId(int position) {
60         return mDelegateAdapter.getItemId(position);
61     }
62 
63     @Override
getItemViewType(int position)64     public int getItemViewType(int position) {
65         return mDelegateAdapter.getItemViewType(position);
66     }
67 
68     @Override
getStateRestorationPolicyInt()69     public int getStateRestorationPolicyInt() {
70         return mDelegateAdapter.getStateRestorationPolicy().ordinal();
71     }
72 
73     @Override
onAttachedToRecyclerView(RecyclerViewOEMV1 recyclerViewOEMV1)74     public void onAttachedToRecyclerView(RecyclerViewOEMV1 recyclerViewOEMV1) {
75         //TODO: CarUiListItemAdapterAdapterV1 passes a null here. Is there a better path
76         // are we wanting clients to call these methods
77         mDelegateAdapter.onAttachedToRecyclerView(null);
78     }
79 
80     @Override
onDetachedFromRecyclerView(RecyclerViewOEMV1 recyclerViewOEMV1)81     public void onDetachedFromRecyclerView(RecyclerViewOEMV1 recyclerViewOEMV1) {
82         //TODO: CarUiListItemAdapterAdapterV1 passes a null here. Is there a better path
83         // are we wanting clients to call these methods
84         mDelegateAdapter.onDetachedFromRecyclerView(null);
85     }
86 
87     @Override
bindViewHolder(ViewHolderWrapper viewHolderWrapper, int position)88     public void bindViewHolder(ViewHolderWrapper viewHolderWrapper, int position) {
89         mDelegateAdapter.onBindViewHolder(viewHolderWrapper.getViewHolder(), position);
90     }
91 
92     @Override
createViewHolder(ViewGroup viewGroup, int viewType)93     public ViewHolderWrapper createViewHolder(ViewGroup viewGroup, int viewType) {
94         // Fake parent need for the correct context
95         FrameLayout fakeParent = new FrameLayout(mPluginContext);
96         return new ViewHolderWrapper(mDelegateAdapter.createViewHolder(fakeParent, viewType));
97     }
98 
99     @Override
onFailedToRecycleView(ViewHolderWrapper viewHolderWrapper)100     public boolean onFailedToRecycleView(ViewHolderWrapper viewHolderWrapper) {
101         return mDelegateAdapter.onFailedToRecycleView(viewHolderWrapper.getViewHolder());
102     }
103 
104     @Override
onViewAttachedToWindow(ViewHolderWrapper viewHolderWrapper)105     public void onViewAttachedToWindow(ViewHolderWrapper viewHolderWrapper) {
106         mDelegateAdapter.onViewAttachedToWindow(viewHolderWrapper.getViewHolder());
107     }
108 
109     @Override
onViewDetachedFromWindow(ViewHolderWrapper viewHolderWrapper)110     public void onViewDetachedFromWindow(ViewHolderWrapper viewHolderWrapper) {
111         mDelegateAdapter.onViewDetachedFromWindow(viewHolderWrapper.getViewHolder());
112     }
113 
114     @Override
onViewRecycled(ViewHolderWrapper viewHolderWrapper)115     public void onViewRecycled(ViewHolderWrapper viewHolderWrapper) {
116         mDelegateAdapter.onViewRecycled(viewHolderWrapper.getViewHolder());
117     }
118 
119 
120     @Override
registerAdapterDataObserver(AdapterDataObserverOEMV1 observer)121     public void registerAdapterDataObserver(AdapterDataObserverOEMV1 observer) {
122         if (observer == null) {
123             return;
124         }
125         mAdapterDataObservers.add(observer);
126         if (!mDelegateAdapter.hasObservers()) {
127             mDelegateAdapter.registerAdapterDataObserver(mAdapterDataObserver);
128         }
129     }
130 
131     @Override
unregisterAdapterDataObserver(AdapterDataObserverOEMV1 observer)132     public void unregisterAdapterDataObserver(AdapterDataObserverOEMV1 observer) {
133         if (observer == null) {
134             return;
135         }
136         mAdapterDataObservers.remove(observer);
137         if (mAdapterDataObservers.isEmpty()) {
138             mDelegateAdapter.unregisterAdapterDataObserver(mAdapterDataObserver);
139         }
140     }
141 
142     @Override
hasStableIds()143     public boolean hasStableIds() {
144         return mDelegateAdapter.hasStableIds();
145     }
146 
147 
148     @Override
setMaxItems(int i)149     public void setMaxItems(int i) {
150         mDelegateAdapter.setMaxItems(i);
151     }
152 
153 
154     @NonNull
155     private final List<AdapterDataObserverOEMV1> mAdapterDataObservers = new ArrayList<>();
156     private final RecyclerView.AdapterDataObserver mAdapterDataObserver =
157             new RecyclerView.AdapterDataObserver() {
158                 @Override
159                 public void onChanged() {
160                     for (AdapterDataObserverOEMV1 observer : mAdapterDataObservers) {
161                         observer.onChanged();
162                     }
163                 }
164 
165                 @Override
166                 public void onItemRangeChanged(int positionStart, int itemCount) {
167                     for (AdapterDataObserverOEMV1 observer : mAdapterDataObservers) {
168                         observer.onItemRangeChanged(positionStart, itemCount);
169                     }
170                 }
171 
172                 @Override
173                 public void onItemRangeChanged(int positionStart, int itemCount,
174                         @Nullable Object payload) {
175                     for (AdapterDataObserverOEMV1 observer : mAdapterDataObservers) {
176                         observer.onItemRangeChanged(positionStart, itemCount, payload);
177                     }
178                 }
179 
180                 @Override
181                 public void onItemRangeInserted(int positionStart, int itemCount) {
182                     for (AdapterDataObserverOEMV1 observer : mAdapterDataObservers) {
183                         observer.onItemRangeInserted(positionStart, itemCount);
184                     }
185                 }
186 
187                 @Override
188                 public void onItemRangeRemoved(int positionStart, int itemCount) {
189                     for (AdapterDataObserverOEMV1 observer : mAdapterDataObservers) {
190                         observer.onItemRangeRemoved(positionStart, itemCount);
191                     }
192                 }
193 
194                 @Override
195                 public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
196                     for (AdapterDataObserverOEMV1 observer : mAdapterDataObservers) {
197                         for (int i = 0; i < itemCount; i++) {
198                             observer.onItemMoved(fromPosition + i, toPosition + i);
199                         }
200                     }
201                 }
202 
203                 @Override
204                 public void onStateRestorationPolicyChanged() {
205                     for (AdapterDataObserverOEMV1 observer : mAdapterDataObservers) {
206                         observer.onStateRestorationPolicyChanged();
207                     }
208                 }
209             };
210 
211     /**
212      * Holds views for each element in the list.
213      */
214     public static class ViewHolderWrapper implements ViewHolderOEMV1 {
215         @NonNull
216         private final RecyclerView.ViewHolder mViewHolder;
217 
ViewHolderWrapper(@onNull RecyclerView.ViewHolder viewHolder)218         ViewHolderWrapper(@NonNull RecyclerView.ViewHolder viewHolder) {
219             mViewHolder = viewHolder;
220         }
221 
222         @NonNull
getViewHolder()223         public RecyclerView.ViewHolder getViewHolder() {
224             return mViewHolder;
225         }
226 
227         @Override
isRecyclable()228         public boolean isRecyclable() {
229             return mViewHolder.isRecyclable();
230         }
231 
232         @Override
getItemView()233         public View getItemView() {
234             return mViewHolder.itemView;
235         }
236     }
237 }
238