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