1 /*
2  * Copyright (C) 2016 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.android.tv.dvr.ui.browse;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.support.annotation.CallSuper;
22 import androidx.leanback.widget.Presenter;
23 import android.view.View;
24 import android.view.View.OnClickListener;
25 import android.view.ViewGroup;
26 import com.android.tv.common.SoftPreconditions;
27 import com.android.tv.dvr.ui.DvrUiHelper;
28 import java.util.HashSet;
29 import java.util.Set;
30 
31 /**
32  * An abstract class to present DVR items in {@link RecordingCardView}, which is mainly used in
33  * {@link DvrBrowseFragment}. DVR items might include: {@link
34  * com.android.tv.dvr.data.ScheduledRecording}, {@link com.android.tv.dvr.data.RecordedProgram}, and
35  * {@link com.android.tv.dvr.data.SeriesRecording}.
36  */
37 public abstract class DvrItemPresenter<T> extends Presenter {
38     protected final Context mContext;
39     private final Set<DvrItemViewHolder> mBoundViewHolders = new HashSet<>();
40     private final OnClickListener mOnClickListener = onCreateOnClickListener();
41 
42     protected class DvrItemViewHolder extends ViewHolder {
DvrItemViewHolder(RecordingCardView view)43         DvrItemViewHolder(RecordingCardView view) {
44             super(view);
45         }
46 
getView()47         protected RecordingCardView getView() {
48             return (RecordingCardView) view;
49         }
50 
onBound(T item)51         protected void onBound(T item) {}
52 
onUnbound()53         protected void onUnbound() {}
54     }
55 
DvrItemPresenter(Context context)56     DvrItemPresenter(Context context) {
57         mContext = context;
58     }
59 
60     @Override
onCreateViewHolder(ViewGroup parent)61     public final ViewHolder onCreateViewHolder(ViewGroup parent) {
62         return onCreateDvrItemViewHolder();
63     }
64 
65     @Override
onBindViewHolder(ViewHolder baseHolder, Object item)66     public final void onBindViewHolder(ViewHolder baseHolder, Object item) {
67         DvrItemViewHolder viewHolder;
68         T dvrItem;
69         try {
70             viewHolder = (DvrItemViewHolder) baseHolder;
71             Class<T> itemType = (Class<T>) item.getClass();
72             dvrItem = itemType.cast(item);
73         } catch (ClassCastException e) {
74             SoftPreconditions.checkState(false);
75             return;
76         }
77         viewHolder.view.setTag(item);
78         viewHolder.view.setOnClickListener(mOnClickListener);
79         onBindDvrItemViewHolder(viewHolder, dvrItem);
80         viewHolder.onBound(dvrItem);
81         mBoundViewHolders.add(viewHolder);
82     }
83 
84     @Override
85     @CallSuper
onUnbindViewHolder(ViewHolder baseHolder)86     public void onUnbindViewHolder(ViewHolder baseHolder) {
87         DvrItemViewHolder viewHolder = (DvrItemViewHolder) baseHolder;
88         mBoundViewHolders.remove(viewHolder);
89         viewHolder.onUnbound();
90         viewHolder.view.setTag(null);
91         viewHolder.view.setOnClickListener(null);
92     }
93 
94     /** Unbinds all bound view holders. */
unbindAllViewHolders()95     public void unbindAllViewHolders() {
96         // When browse fragments are destroyed, RecyclerView would not call presenters'
97         // onUnbindViewHolder(). We should handle it by ourselves to prevent resources leaks.
98         for (ViewHolder viewHolder : new HashSet<>(mBoundViewHolders)) {
99             onUnbindViewHolder(viewHolder);
100         }
101     }
102 
103     /** This method will be called when a {@link DvrItemViewHolder} is needed to be created. */
onCreateDvrItemViewHolder()104     protected abstract DvrItemViewHolder onCreateDvrItemViewHolder();
105 
106     /** This method will be called when a {@link DvrItemViewHolder} is bound to a DVR item. */
onBindDvrItemViewHolder(DvrItemViewHolder viewHolder, T item)107     protected abstract void onBindDvrItemViewHolder(DvrItemViewHolder viewHolder, T item);
108 
109     /** Returns context. */
getContext()110     protected Context getContext() {
111         return mContext;
112     }
113 
114     /** Creates {@link OnClickListener} for DVR library's card views. */
onCreateOnClickListener()115     protected OnClickListener onCreateOnClickListener() {
116         return new OnClickListener() {
117             @Override
118             public void onClick(View view) {
119                 if (view instanceof RecordingCardView) {
120                     RecordingCardView v = (RecordingCardView) view;
121                     DvrUiHelper.startDetailsActivity(
122                             (Activity) v.getContext(), v.getTag(), v.getImageView(), false);
123                 }
124             }
125         };
126     }
127 }
128