1 /* 2 * Copyright (C) 2017 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 com.android.car.media.drawer; 17 18 import android.content.Context; 19 import android.graphics.Bitmap; 20 import android.media.MediaDescription; 21 import android.text.TextUtils; 22 23 import com.android.car.app.CarDrawerAdapter; 24 import com.android.car.app.DrawerItemViewHolder; 25 import com.android.car.apps.common.BitmapDownloader; 26 import com.android.car.apps.common.BitmapWorkerOptions; 27 import com.android.car.apps.common.UriUtils; 28 import com.android.car.media.R; 29 30 /** 31 * Component that handles fetching of items for {@link MediaDrawerAdapter}. 32 * <p> 33 * It also handles ViewHolder population and item clicks. 34 */ 35 interface MediaItemsFetcher { 36 public static final int DONT_SCROLL = -1; 37 38 /** 39 * Used to inform owning {@link MediaDrawerAdapter} that items have changed. 40 */ 41 interface ItemsUpdatedCallback { onItemsUpdated()42 void onItemsUpdated(); 43 } 44 45 /** 46 * Kick-off fetching/monitoring of items. 47 * 48 * @param callback Callback that is invoked when items are first loaded ar if they change 49 * subsequently. 50 */ start(ItemsUpdatedCallback callback)51 void start(ItemsUpdatedCallback callback); 52 53 /** 54 * @return Number of items currently fetched. 55 */ getItemCount()56 int getItemCount(); 57 58 /** 59 * Used to indicate the kind of layout (small or normal) to use for the views that will display 60 * this item in a {@link CarDrawerAdapter}. See {@link CarDrawerAdapter#usesSmallLayout} 61 * 62 * @param position Adapter position of item 63 * @return Whether to use small (true) or normal layout (false). 64 */ usesSmallLayout(int position)65 boolean usesSmallLayout(int position); 66 67 /** 68 * Used by owning {@link MediaDrawerAdapter} to populate views. 69 * 70 * @param holder View-holder to populate. 71 * @param position Item position. 72 */ populateViewHolder(DrawerItemViewHolder holder, int position)73 void populateViewHolder(DrawerItemViewHolder holder, int position); 74 75 /** 76 * Used by owning {@link MediaDrawerAdapter} to handle clicks. 77 * 78 * @param position Item position. 79 */ onItemClick(int position)80 void onItemClick(int position); 81 82 /** 83 * Used when this instance is going to be released. Subclasses should release resources. 84 */ cleanup()85 void cleanup(); 86 87 88 /** 89 * Get the position to scroll to if any. 90 * @return An integer greater than or equal to 0 if there is a position to scroll to, the 91 * constant {@link DONT_SCROLL} otherwise. 92 */ getScrollPosition()93 int getScrollPosition(); 94 95 /** 96 * Utility method to determine if description can be displayed in a small layout. 97 */ usesSmallLayout(MediaDescription description)98 static boolean usesSmallLayout(MediaDescription description) { 99 // Small layout is sufficient if there's no sub-title to display for the item. 100 return TextUtils.isEmpty(description.getSubtitle()); 101 } 102 103 /** 104 * Utility method to populate {@code holder} with details from {@code description}. It populates 105 * title, text and icon at most. 106 */ populateViewHolderFrom(DrawerItemViewHolder holder, MediaDescription description)107 static void populateViewHolderFrom(DrawerItemViewHolder holder, MediaDescription description) { 108 Context context = holder.itemView.getContext(); 109 holder.getTitle().setText(description.getTitle()); 110 // If normal layout, populate subtitle. 111 if (!usesSmallLayout(description)) { 112 holder.getText().setText(description.getSubtitle()); 113 } 114 Bitmap iconBitmap = description.getIconBitmap(); 115 holder.getIcon().setImageBitmap(iconBitmap); // Ok to set null here for clearing. 116 if (iconBitmap == null && description.getIconUri() != null) { 117 int bitmapSize = 118 context.getResources().getDimensionPixelSize(R.dimen.car_list_item_icon_size); 119 // We don't want to cache android resources as they are needed to be refreshed after 120 // configuration changes. 121 int cacheFlag = UriUtils.isAndroidResourceUri(description.getIconUri()) 122 ? (BitmapWorkerOptions.CACHE_FLAG_DISK_DISABLED 123 | BitmapWorkerOptions.CACHE_FLAG_MEM_DISABLED) 124 : 0; 125 BitmapWorkerOptions options = new BitmapWorkerOptions.Builder(context) 126 .resource(description.getIconUri()) 127 .height(bitmapSize) 128 .width(bitmapSize) 129 .cacheFlag(cacheFlag) 130 .build(); 131 BitmapDownloader.getInstance(context).loadBitmap(options, holder.getIcon()); 132 } 133 } 134 } 135