| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.launcher3.widget.picker; |
| |
| import android.content.Context; |
| import android.util.Log; |
| import android.util.SparseArray; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.View.OnClickListener; |
| import android.view.View.OnLongClickListener; |
| import android.view.ViewGroup; |
| |
| import androidx.recyclerview.widget.RecyclerView; |
| import androidx.recyclerview.widget.RecyclerView.Adapter; |
| import androidx.recyclerview.widget.RecyclerView.ViewHolder; |
| |
| import com.android.launcher3.R; |
| import com.android.launcher3.WidgetPreviewLoader; |
| import com.android.launcher3.icons.IconCache; |
| import com.android.launcher3.recyclerview.ViewHolderBinder; |
| import com.android.launcher3.util.LabelComparator; |
| import com.android.launcher3.widget.WidgetCell; |
| import com.android.launcher3.widget.model.WidgetsListBaseEntry; |
| import com.android.launcher3.widget.model.WidgetsListContentEntry; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| /** |
| * List view adapter for the widget tray. |
| * |
| * <p>Memory vs. Performance: |
| * The less number of types of views are inserted into a {@link RecyclerView}, the more recycling |
| * happens and less memory is consumed. |
| */ |
| public class WidgetsListAdapter extends Adapter<ViewHolder> { |
| |
| private static final String TAG = "WidgetsListAdapter"; |
| private static final boolean DEBUG = false; |
| |
| /** Uniquely identifies widgets list view type within the app. */ |
| private static final int VIEW_TYPE_WIDGETS_LIST = R.layout.widgets_list_row_view; |
| |
| private final WidgetsDiffReporter mDiffReporter; |
| private final SparseArray<ViewHolderBinder> mViewHolderBinders = new SparseArray<>(); |
| private final WidgetsListRowViewHolderBinder mWidgetsListRowViewHolderBinder; |
| |
| private ArrayList<WidgetsListBaseEntry> mEntries = new ArrayList<>(); |
| |
| public WidgetsListAdapter(Context context, LayoutInflater layoutInflater, |
| WidgetPreviewLoader widgetPreviewLoader, IconCache iconCache, |
| OnClickListener iconClickListener, OnLongClickListener iconLongClickListener) { |
| mDiffReporter = new WidgetsDiffReporter(iconCache, this); |
| mWidgetsListRowViewHolderBinder = new WidgetsListRowViewHolderBinder(context, |
| layoutInflater, iconClickListener, iconLongClickListener, widgetPreviewLoader); |
| mViewHolderBinders.put(VIEW_TYPE_WIDGETS_LIST, mWidgetsListRowViewHolderBinder); |
| } |
| |
| /** |
| * Defers applying bitmap on all the {@link WidgetCell} in the {@param rv}. |
| * |
| * @see WidgetCell#setApplyBitmapDeferred(boolean) |
| */ |
| public void setApplyBitmapDeferred(boolean isDeferred, RecyclerView rv) { |
| mWidgetsListRowViewHolderBinder.setApplyBitmapDeferred(isDeferred); |
| |
| for (int i = rv.getChildCount() - 1; i >= 0; i--) { |
| ViewHolder viewHolder = rv.getChildViewHolder(rv.getChildAt(i)); |
| if (viewHolder.getItemViewType() == VIEW_TYPE_WIDGETS_LIST) { |
| WidgetsRowViewHolder holder = (WidgetsRowViewHolder) viewHolder; |
| for (int j = holder.cellContainer.getChildCount() - 1; j >= 0; j--) { |
| View v = holder.cellContainer.getChildAt(j); |
| if (v instanceof WidgetCell) { |
| ((WidgetCell) v).setApplyBitmapDeferred(isDeferred); |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| public int getItemCount() { |
| return mEntries.size(); |
| } |
| |
| /** Gets the section name for {@link com.android.launcher3.views.RecyclerViewFastScroller}. */ |
| public String getSectionName(int pos) { |
| return mEntries.get(pos).mTitleSectionName; |
| } |
| |
| /** Updates the widget list. */ |
| public void setWidgets(List<WidgetsListBaseEntry> tempEntries) { |
| ArrayList<WidgetsListBaseEntry> newEntries = new ArrayList<>(tempEntries); |
| WidgetListBaseRowEntryComparator rowComparator = new WidgetListBaseRowEntryComparator(); |
| Collections.sort(newEntries, rowComparator); |
| mDiffReporter.process(mEntries, newEntries, rowComparator); |
| } |
| |
| @Override |
| public void onBindViewHolder(ViewHolder holder, int pos) { |
| ViewHolderBinder viewHolderBinder = mViewHolderBinders.get(getItemViewType(pos)); |
| viewHolderBinder.bindViewHolder(holder, mEntries.get(pos)); |
| } |
| |
| @Override |
| public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { |
| if (DEBUG) { |
| Log.v(TAG, "\nonCreateViewHolder"); |
| } |
| |
| return mViewHolderBinders.get(viewType).newViewHolder(parent); |
| } |
| |
| @Override |
| public void onViewRecycled(ViewHolder holder) { |
| mViewHolderBinders.get(holder.getItemViewType()).unbindViewHolder(holder); |
| } |
| |
| @Override |
| public boolean onFailedToRecycleView(ViewHolder holder) { |
| // If child views are animating, then the RecyclerView may choose not to recycle the view, |
| // causing extraneous onCreateViewHolder() calls. It is safe in this case to continue |
| // recycling this view, and take care in onViewRecycled() to cancel any existing |
| // animations. |
| return true; |
| } |
| |
| @Override |
| public long getItemId(int pos) { |
| return pos; |
| } |
| |
| @Override |
| public int getItemViewType(int pos) { |
| WidgetsListBaseEntry entry = mEntries.get(pos); |
| if (entry instanceof WidgetsListContentEntry) { |
| return VIEW_TYPE_WIDGETS_LIST; |
| } |
| throw new UnsupportedOperationException("ViewHolderBinder not found for " + entry); |
| } |
| |
| /** Comparator for sorting WidgetListRowEntry based on package title. */ |
| public static class WidgetListBaseRowEntryComparator implements |
| Comparator<WidgetsListBaseEntry> { |
| |
| private final LabelComparator mComparator = new LabelComparator(); |
| |
| @Override |
| public int compare(WidgetsListBaseEntry a, WidgetsListBaseEntry b) { |
| return mComparator.compare(a.mPkgItem.title.toString(), b.mPkgItem.title.toString()); |
| } |
| } |
| } |