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.support.annotation.Nullable; 20 import android.support.v7.widget.RecyclerView; 21 22 import androidx.car.drawer.CarDrawerAdapter; 23 import androidx.car.drawer.CarDrawerController; 24 import androidx.car.drawer.DrawerItemViewHolder; 25 26 /** 27 * Subclass of CarDrawerAdapter used by the Media app. 28 * <p> 29 * This adapter delegates actual fetching of items (and other operations) to a 30 * {@link MediaItemsFetcher}. The current fetcher being used can be updated at runtime. 31 */ 32 class MediaDrawerAdapter extends CarDrawerAdapter { 33 private final CarDrawerController mDrawerController; 34 private MediaItemsFetcher mCurrentFetcher; 35 private MediaFetchCallback mFetchCallback; 36 private int mCurrentScrollPosition; 37 38 /** 39 * Interface for a callback object that will be notified of changes to the fetch status of 40 * items in a media drawer. 41 */ 42 interface MediaFetchCallback { 43 /** 44 * Called when a fetch for items starts. 45 */ 46 void onFetchStart(); 47 48 /** 49 * Called when a fetch for items ends. 50 */ 51 void onFetchEnd(); 52 } 53 54 MediaDrawerAdapter(Context context, CarDrawerController drawerController) { 55 super(context, true /* showDisabledListOnEmpty */); 56 mDrawerController = drawerController; 57 } 58 59 /** 60 * Sets the object to be notified of changes to the fetching of items in the media drawer. 61 */ 62 void setFetchCallback(@Nullable MediaFetchCallback callback) { 63 mFetchCallback = callback; 64 } 65 66 /** 67 * Switch the {@link MediaItemsFetcher} being used to fetch items. The new fetcher is kicked-off 68 * and the drawer's content's will be updated to show newly loaded items. Any old fetcher is 69 * cleaned up and released. 70 * 71 * @param fetcher New {@link MediaItemsFetcher} to use for display Drawer items. 72 */ 73 void setFetcherAndInvoke(MediaItemsFetcher fetcher) { 74 setFetcher(fetcher); 75 76 if (mFetchCallback != null) { 77 mFetchCallback.onFetchStart(); 78 } 79 80 mCurrentFetcher.start(() -> { 81 closeFetch(); 82 notifyDataSetChanged(); 83 }); 84 } 85 86 void setFetcher(MediaItemsFetcher fetcher) { 87 if (mCurrentFetcher != null) { 88 mCurrentFetcher.cleanup(); 89 } 90 mCurrentFetcher = fetcher; 91 notifyDataSetChanged(); 92 } 93 94 @Override 95 protected int getActualItemCount() { 96 return mCurrentFetcher != null ? mCurrentFetcher.getItemCount() : 0; 97 } 98 99 @Override 100 protected boolean usesSmallLayout(int position) { 101 return mCurrentFetcher.usesSmallLayout(position); 102 } 103 104 @Override 105 protected void populateViewHolder(DrawerItemViewHolder holder, int position) { 106 if (mCurrentFetcher == null) { 107 return; 108 } 109 110 mCurrentFetcher.populateViewHolder(holder, position); 111 scrollToCurrent(); 112 } 113 114 @Override 115 public void onItemClick(int position) { 116 if (mCurrentFetcher != null) { 117 mCurrentFetcher.onItemClick(position); 118 } 119 } 120 121 @Override 122 public void cleanup() { 123 super.cleanup(); 124 if (mCurrentFetcher != null) { 125 mCurrentFetcher.cleanup(); 126 mCurrentFetcher = null; 127 notifyDataSetChanged(); 128 } 129 closeFetch(); 130 } 131 132 private void closeFetch() { 133 if (mFetchCallback != null) { 134 mFetchCallback.onFetchEnd(); 135 mFetchCallback = null; 136 } 137 } 138 139 public void scrollToCurrent() { 140 if (mCurrentFetcher == null) { 141 return; 142 } 143 int scrollPosition = mCurrentFetcher.getScrollPosition(); 144 if (scrollPosition != MediaItemsFetcher.DONT_SCROLL 145 && mCurrentScrollPosition != scrollPosition) { 146 mDrawerController.scrollToPosition(scrollPosition); 147 mCurrentScrollPosition = scrollPosition; 148 } 149 } 150 151 @Override 152 public void onAttachedToRecyclerView(RecyclerView recyclerView) { 153 if (mCurrentFetcher != null) { 154 MediaItemsFetcher fetcher = mCurrentFetcher; 155 fetcher.cleanup(); 156 setFetcherAndInvoke(fetcher); 157 } 158 } 159 160 } 161