120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn/* 220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Copyright (C) 2014 The Android Open Source Project 320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * in compliance with the License. You may obtain a copy of the License at 620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * http://www.apache.org/licenses/LICENSE-2.0 820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Unless required by applicable law or agreed to in writing, software distributed under the License 1020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * or implied. See the License for the specific language governing permissions and limitations under 1220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * the License. 1320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 1420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournpackage android.support.v17.leanback.widget; 1520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 1620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournimport android.view.View; 1720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbournimport android.view.ViewGroup; 1820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 1908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Guimport java.util.HashMap; 2008a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangliimport java.util.List; 2108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Guimport java.util.Map; 2208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu 2320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn/** 2420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * A Presenter is used to generate {@link View}s and bind Objects to them on 25a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * demand. It is closely related to the concept of an {@link 2660d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, but is 27a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * not position-based. The leanback framework implements the adapter concept using 28a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * {@link ObjectAdapter} which refers to a Presenter (or {@link PresenterSelector}) instance. 29a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * 30a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p> 31a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Presenters should be stateless. Presenters typically extend {@link ViewHolder} to store all 32a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * necessary view state information, such as references to child views to be used when 33a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * binding to avoid expensive calls to {@link View#findViewById(int)}. 34a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p> 3520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 3620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * <p> 3720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * A trivial Presenter that takes a string and renders it into a {@link 3860d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * android.widget.TextView TextView}: 3920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 4020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * <pre class="prettyprint"> 4120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * public class StringTextViewPresenter extends Presenter { 4220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * // This class does not need a custom ViewHolder, since it does not use 4320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * // a complex layout. 4420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 4520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * {@literal @}Override 4660d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * public ViewHolder onCreateViewHolder(ViewGroup parent) { 4720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * return new ViewHolder(new TextView(parent.getContext())); 4820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 4920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 5020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * {@literal @}Override 5160d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * public void onBindViewHolder(ViewHolder viewHolder, Object item) { 5220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * String str = (String) item; 5320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * TextView textView = (TextView) viewHolder.mView; 5420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 5520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * textView.setText(item); 5620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 5720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * 5820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * {@literal @}Override 5960d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * public void onUnbindViewHolder(ViewHolder viewHolder) { 6060d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * // Nothing to unbind for TextView, but if this viewHolder had 6160d34fdccbe92a77e01b2cc63ffcab092a91009fTim Kilbourn * // allocated bitmaps, they can be released here. 6220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 6320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * } 6420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * </pre> 6508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * In addition to view creation and binding, Presenter allows dynamic interface (facet) to 6608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * be added: {@link #setFacet(Class, Object)}. Supported facets: 6708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * <li> {@link ItemAlignmentFacet} is used by {@link HorizontalGridView} and 6808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * {@link VerticalGridView} to customize child alignment. 6920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 7008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gupublic abstract class Presenter implements FacetProvider { 7120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 7220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * ViewHolder can be subclassed and used to cache any view accessors needed 7320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * to improve binding performance (for example, results of findViewById) 7420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * without needing to subclass a View. 7520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 7608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu public static class ViewHolder implements FacetProvider { 7720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public final View view; 7808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu private Map<Class, Object> mFacets; 7920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 8020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public ViewHolder(View view) { 8120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn this.view = view; 8220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 8308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu 8408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu @Override 8508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu public final Object getFacet(Class<?> facetClass) { 8608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu if (mFacets == null) { 8708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu return null; 8808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 8908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu return mFacets.get(facetClass); 9008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 9108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu 9208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu /** 9308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * Sets dynamic implemented facet in addition to basic ViewHolder functions. 9408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * @param facetClass Facet classes to query, can be class of {@link ItemAlignmentFacet}. 9508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * @param facetImpl Facet implementation. 9608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu */ 9708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu public final void setFacet(Class<?> facetClass, Object facetImpl) { 9808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu if (mFacets == null) { 9908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu mFacets = new HashMap<Class, Object>(); 10008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 10108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu mFacets.put(facetClass, facetImpl); 10208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 10320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn } 10420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 105cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu /** 106cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu * Base class to perform a task on Presenter.ViewHolder. 107cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu */ 108cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu public static abstract class ViewHolderTask { 109cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu /** 110cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu * Called to perform a task on view holder. 111cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu * @param holder The view holder to perform task. 112cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu */ 113cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu public void run(Presenter.ViewHolder holder) { 114cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu } 115cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu } 116cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu 11708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu private Map<Class, Object> mFacets; 11808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu 11920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 12020c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Creates a new {@link View}. 12120c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 12220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public abstract ViewHolder onCreateViewHolder(ViewGroup parent); 12320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 12420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 12520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Binds a {@link View} to an item. 12620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 12720c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public abstract void onBindViewHolder(ViewHolder viewHolder, Object item); 12820c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn 12920c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn /** 13008a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli * Binds a {@link View} to an item with a list of payloads. 13108a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli * @param viewHolder The ViewHolder which should be updated to represent the contents of the 13208a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli * item at the given position in the data set. 13308a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli * @param item The item which should be bound to view holder. 13408a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli * @param payloads A non-null list of merged payloads. Can be empty list if requires full 13508a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli * update. 13608a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli */ 13708a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli public void onBindViewHolder(ViewHolder viewHolder, Object item, List<Object> payloads) { 13808a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli onBindViewHolder(viewHolder, item); 13908a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli } 14008a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli 14108a38559a3751252fc8a1f36db0a431508a8f7d5jingjiangli /** 14220c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * Unbinds a {@link View} from an item. Any expensive references may be 14320c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * released here, and any fields that are not bound for every item should be 14420c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn * cleared here. 14520c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn */ 14620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn public abstract void onUnbindViewHolder(ViewHolder viewHolder); 14747520b68e50572a9775a662410c5aff8300c8784Craig Stout 14847520b68e50572a9775a662410c5aff8300c8784Craig Stout /** 14947520b68e50572a9775a662410c5aff8300c8784Craig Stout * Called when a view created by this presenter has been attached to a window. 15047520b68e50572a9775a662410c5aff8300c8784Craig Stout * 15147520b68e50572a9775a662410c5aff8300c8784Craig Stout * <p>This can be used as a reasonable signal that the view is about to be seen 15247520b68e50572a9775a662410c5aff8300c8784Craig Stout * by the user. If the adapter previously freed any resources in 15347520b68e50572a9775a662410c5aff8300c8784Craig Stout * {@link #onViewDetachedFromWindow(ViewHolder)} 15447520b68e50572a9775a662410c5aff8300c8784Craig Stout * those resources should be restored here.</p> 15547520b68e50572a9775a662410c5aff8300c8784Craig Stout * 15647520b68e50572a9775a662410c5aff8300c8784Craig Stout * @param holder Holder of the view being attached 15747520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 15847520b68e50572a9775a662410c5aff8300c8784Craig Stout public void onViewAttachedToWindow(ViewHolder holder) { 15947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 16047520b68e50572a9775a662410c5aff8300c8784Craig Stout 16147520b68e50572a9775a662410c5aff8300c8784Craig Stout /** 16247520b68e50572a9775a662410c5aff8300c8784Craig Stout * Called when a view created by this presenter has been detached from its window. 16347520b68e50572a9775a662410c5aff8300c8784Craig Stout * 16447520b68e50572a9775a662410c5aff8300c8784Craig Stout * <p>Becoming detached from the window is not necessarily a permanent condition; 16547520b68e50572a9775a662410c5aff8300c8784Craig Stout * the consumer of an presenter's views may choose to cache views offscreen while they 166ef9d4aa4eb25e5a0e6ec3ff7c406ced131726ff2Nick Chalko * are not visible, attaching and detaching them as appropriate.</p> 16747520b68e50572a9775a662410c5aff8300c8784Craig Stout * 1685358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * Any view property animations should be cancelled here or the view may fail 1695358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * to be recycled. 1705358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * 17147520b68e50572a9775a662410c5aff8300c8784Craig Stout * @param holder Holder of the view being detached 17247520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 17347520b68e50572a9775a662410c5aff8300c8784Craig Stout public void onViewDetachedFromWindow(ViewHolder holder) { 1745358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout // If there are view property animations running then RecyclerView won't recycle. 1755358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout cancelAnimationsRecursive(holder.view); 1765358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 1775358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout 1785358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout /** 1795358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout * Utility method for removing all running animations on a view. 1805358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout */ 1815358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout protected static void cancelAnimationsRecursive(View view) { 182b455339a4d442068dd312fb93c0544106810dfadDake Gu if (view != null && view.hasTransientState()) { 1835358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout view.animate().cancel(); 1845358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout if (view instanceof ViewGroup) { 1855358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout final int count = ((ViewGroup) view).getChildCount(); 1865358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout for (int i = 0; view.hasTransientState() && i < count; i++) { 1875358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout cancelAnimationsRecursive(((ViewGroup) view).getChildAt(i)); 1885358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 1895358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 1905358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout } 19147520b68e50572a9775a662410c5aff8300c8784Craig Stout } 19247520b68e50572a9775a662410c5aff8300c8784Craig Stout 1937ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout /** 1947ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Called to set a click listener for the given view holder. 1957ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * 1967ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * The default implementation sets the click listener on the root view in the view holder. 1977ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * If the root view isn't focusable this method should be overridden to set the listener 1987ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * on the appropriate focusable child view(s). 1997ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * 2007ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * @param holder The view holder containing the view(s) on which the listener should be set. 2017ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * @param listener The click listener to be set. 2027ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */ 2037ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout public void setOnClickListener(ViewHolder holder, View.OnClickListener listener) { 2047ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout holder.view.setOnClickListener(listener); 2057ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout } 20608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu 20708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu @Override 20808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu public final Object getFacet(Class<?> facetClass) { 20908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu if (mFacets == null) { 21008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu return null; 21108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 21208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu return mFacets.get(facetClass); 21308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 21408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu 21508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu /** 21608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * Sets dynamic implemented facet in addition to basic Presenter functions. 21708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * @param facetClass Facet classes to query, can be class of {@link ItemAlignmentFacet}. 21808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu * @param facetImpl Facet implementation. 21908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu */ 22008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu public final void setFacet(Class<?> facetClass, Object facetImpl) { 22108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu if (mFacets == null) { 22208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu mFacets = new HashMap<Class, Object>(); 22308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 22408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu mFacets.put(facetClass, facetImpl); 22508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu } 22620c094c196271089a7119a965b6a99786ea9ed36Tim Kilbourn} 227