diff options
Diffstat (limited to 'src/com/android/tv/menu/ChannelsRowAdapter.java')
-rw-r--r-- | src/com/android/tv/menu/ChannelsRowAdapter.java | 198 |
1 files changed, 137 insertions, 61 deletions
diff --git a/src/com/android/tv/menu/ChannelsRowAdapter.java b/src/com/android/tv/menu/ChannelsRowAdapter.java index c8e1bd05..7ff44ea6 100644 --- a/src/com/android/tv/menu/ChannelsRowAdapter.java +++ b/src/com/android/tv/menu/ChannelsRowAdapter.java @@ -31,17 +31,15 @@ import com.android.tv.dvr.DvrDataManager; import com.android.tv.recommendation.Recommender; import com.android.tv.util.SetupUtils; import com.android.tv.util.TvInputManagerHelper; -import com.android.tv.util.Utils; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; /** * An adapter of the Channels row. */ -public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<Channel> { - private static final String TAG = "ChannelsRowAdapter"; - +public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<ChannelsRowItem> { // There are four special cards: guide, setup, dvr, applink. private static final int SIZE_OF_VIEW_TYPE = 5; @@ -51,7 +49,6 @@ public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<Channel> private final DvrDataManager mDvrDataManager; private final int mMaxCount; private final int mMinCount; - private final int[] mViewType = new int[SIZE_OF_VIEW_TYPE]; private final View.OnClickListener mGuideOnClickListener = new View.OnClickListener() { @Override @@ -113,14 +110,12 @@ public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<Channel> mRecommender = recommender; mMinCount = minCount; mMaxCount = maxCount; + setHasStableIds(true); } @Override public int getItemViewType(int position) { - if (position >= SIZE_OF_VIEW_TYPE) { - return R.layout.menu_card_channel; - } - return mViewType[position]; + return getItemList().get(position).getLayoutId(); } @Override @@ -129,9 +124,12 @@ public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<Channel> } @Override - public void onBindViewHolder(MyViewHolder viewHolder, int position) { - super.onBindViewHolder(viewHolder, position); + public long getItemId(int position) { + return getItemList().get(position).getItemId(); + } + @Override + public void onBindViewHolder(MyViewHolder viewHolder, int position) { int viewType = getItemViewType(position); if (viewType == R.layout.menu_card_guide) { viewHolder.itemView.setOnClickListener(mGuideOnClickListener); @@ -144,80 +142,158 @@ public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<Channel> SimpleCardView view = (SimpleCardView) viewHolder.itemView; view.setText(R.string.channels_item_dvr); } else { - viewHolder.itemView.setTag(getItemList().get(position)); + viewHolder.itemView.setTag(getItemList().get(position).getChannel()); viewHolder.itemView.setOnClickListener(mChannelOnClickListener); } + super.onBindViewHolder(viewHolder, position); } @Override public void update() { - List<Channel> channelList = new ArrayList<>(); - Channel dummyChannel = new Channel.Builder().build(); - // For guide item - channelList.add(dummyChannel); - // For setup item - TvInputManagerHelper inputManager = TvApplication.getSingletons(mContext) - .getTvInputManagerHelper(); - boolean showSetupCard = SetupUtils.getInstance(mContext).hasNewInput(inputManager); - Channel currentChannel = getMainActivity().getCurrentChannel(); - boolean showAppLinkCard = currentChannel != null - && currentChannel.getAppLinkType(mContext) != Channel.APP_LINK_TYPE_NONE - // Sometimes applicationInfo can be null. b/28932537 - && inputManager.getTvInputAppInfo(currentChannel.getInputId()) != null; - boolean showDvrCard = false; + if (getItemCount() == 0) { + createItems(); + } else { + updateItems(); + } + } + + private void createItems() { + List<ChannelsRowItem> items = new ArrayList<>(); + items.add(ChannelsRowItem.GUIDE_ITEM); + if (needToShowSetupItem()) { + items.add(ChannelsRowItem.SETUP_ITEM); + } + if (needToShowDvrItem()) { + items.add(ChannelsRowItem.DVR_ITEM); + } + if (needToShowAppLinkItem()) { + ChannelsRowItem.APP_LINK_ITEM.setChannel( + new Channel.Builder(getMainActivity().getCurrentChannel()).build()); + items.add(ChannelsRowItem.APP_LINK_ITEM); + } + for (Channel channel : getRecentChannels()) { + items.add(new ChannelsRowItem(channel, R.layout.menu_card_channel)); + } + setItemList(items); + } + + private void updateItems() { + List<ChannelsRowItem> items = getItemList(); + // The current index of the item list to iterate. It starts from 1 because the first item + // (GUIDE) is always visible and not updated. + int currentIndex = 1; + if (updateItem(needToShowSetupItem(), ChannelsRowItem.SETUP_ITEM, currentIndex)) { + ++currentIndex; + } + if (updateItem(needToShowDvrItem(), ChannelsRowItem.DVR_ITEM, currentIndex)) { + ++currentIndex; + } + if (updateItem(needToShowAppLinkItem(), ChannelsRowItem.APP_LINK_ITEM, currentIndex)) { + if (!getMainActivity().getCurrentChannel() + .hasSameReadOnlyInfo(ChannelsRowItem.APP_LINK_ITEM.getChannel())) { + ChannelsRowItem.APP_LINK_ITEM.setChannel( + new Channel.Builder(getMainActivity().getCurrentChannel()).build()); + notifyItemChanged(currentIndex); + } + ++currentIndex; + } + int numOldChannels = items.size() - currentIndex; + if (numOldChannels > 0) { + while (items.size() > currentIndex) { + items.remove(items.size() - 1); + } + notifyItemRangeRemoved(currentIndex, numOldChannels); + } + for (Channel channel : getRecentChannels()) { + items.add(new ChannelsRowItem(channel, R.layout.menu_card_channel)); + } + int numNewChannels = items.size() - currentIndex; + if (numNewChannels > 0) { + notifyItemRangeInserted(currentIndex, numNewChannels); + } + } + + /** + * Returns {@code true} if the item should be shown. + */ + private boolean updateItem(boolean needToShow, ChannelsRowItem item, int index) { + List<ChannelsRowItem> items = getItemList(); + boolean isItemInList = index < items.size() && item.equals(items.get(index)); + if (needToShow && !isItemInList) { + items.add(index, item); + notifyItemInserted(index); + } else if (!needToShow && isItemInList) { + items.remove(index); + notifyItemRemoved(index); + } + return needToShow; + } + + private boolean needToShowSetupItem() { + TvInputManagerHelper inputManager = + TvApplication.getSingletons(mContext).getTvInputManagerHelper(); + return SetupUtils.getInstance(mContext).hasNewInput(inputManager); + } + + private boolean needToShowDvrItem() { + TvInputManagerHelper inputManager = + TvApplication.getSingletons(mContext).getTvInputManagerHelper(); if (mDvrDataManager != null) { for (TvInputInfo info : inputManager.getTvInputInfos(true, true)) { if (info.canRecord()) { - showDvrCard = true; - break; + return true; } } } + return false; + } - mViewType[0] = R.layout.menu_card_guide; - int index = 1; - if (showSetupCard) { - channelList.add(dummyChannel); - mViewType[index++] = R.layout.menu_card_setup; - } - if (showDvrCard) { - channelList.add(dummyChannel); - mViewType[index++] = R.layout.menu_card_dvr; - } - if (showAppLinkCard) { - channelList.add(currentChannel); - mViewType[index++] = R.layout.menu_card_app_link; - } - for ( ; index < mViewType.length; ++index) { - mViewType[index] = R.layout.menu_card_channel; - } - channelList.addAll(getRecentChannels()); - setItemList(channelList); + private boolean needToShowAppLinkItem() { + TvInputManagerHelper inputManager = + TvApplication.getSingletons(mContext).getTvInputManagerHelper(); + Channel currentChannel = getMainActivity().getCurrentChannel(); + return currentChannel != null + && currentChannel.getAppLinkType(mContext) != Channel.APP_LINK_TYPE_NONE + // Sometimes applicationInfo can be null. b/28932537 + && inputManager.getTvInputAppInfo(currentChannel.getInputId()) != null; } private List<Channel> getRecentChannels() { List<Channel> channelList = new ArrayList<>(); + long currentChannelId = getMainActivity().getCurrentChannelId(); + ArrayDeque<Long> recentChannels = getMainActivity().getRecentChannels(); + // Add the last watched channel as the first one. + for (long channelId : recentChannels) { + if (addChannelToList( + channelList, mRecommender.getChannel(channelId), currentChannelId)) { + break; + } + } + // Add the recommended channels. for (Channel channel : mRecommender.recommendChannels(mMaxCount)) { - if (channel.isBrowsable()) { - channelList.add(channel); + if (channelList.size() >= mMaxCount) { + break; } + addChannelToList(channelList, channel, currentChannelId); } - int count = channelList.size(); // If the number of recommended channels is not enough, add more from the recent channel // list. - if (count < mMinCount) { - for (long channelId : getMainActivity().getRecentChannels()) { - Channel channel = mRecommender.getChannel(channelId); - if (channel == null || channelList.contains(channel) - || !channel.isBrowsable()) { - continue; - } - channelList.add(channel); - if (++count >= mMinCount) { - break; - } + for (long channelId : recentChannels) { + if (channelList.size() >= mMinCount) { + break; } + addChannelToList(channelList, mRecommender.getChannel(channelId), currentChannelId); } return channelList; } + + private static boolean addChannelToList( + List<Channel> channelList, Channel channel, long currentChannelId) { + if (channel == null || channel.getId() == currentChannelId + || channelList.contains(channel) || !channel.isBrowsable()) { + return false; + } + channelList.add(channel); + return true; + } } |