19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.preference; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1976f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunneimport java.io.IOException; 2076f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunneimport java.lang.reflect.Constructor; 2176f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunneimport java.util.HashMap; 2276f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 267b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbyeimport android.annotation.XmlRes; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextThemeWrapper; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.InflateException; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// TODO: fix generics 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Generic XML inflater. This has been adapted from {@link LayoutInflater} and 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * quickly passed over to use generics. 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 4176f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne * @param T The type of the items to inflate 4276f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne * @param P The type of parents (that is those items that contain other items). 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Must implement {@link GenericInflater.Parent} 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4576f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunneabstract class GenericInflater<T, P extends GenericInflater.Parent> { 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean DEBUG = false; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final Context mContext; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these are optional, set by the caller 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mFactorySet; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Factory<T> mFactory; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Object[] mConstructorArgs = new Object[2]; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5676f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne private static final Class[] mConstructorSignature = new Class[] { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context.class, AttributeSet.class}; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5976f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne private static final HashMap sConstructorMap = new HashMap(); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mDefaultPackage; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface Parent<T> { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addItemFromInflater(T child); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface Factory<T> { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hook you can supply that is called when inflating from a 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inflater. You can use this to customize the tag 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * names available in your XML files. 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note that it is good practice to prefix these custom names with your 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * package (i.e., com.coolcompany.apps) to avoid conflicts with system 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * names. 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name Tag name to be inflated. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context The context the item is being created in. 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param attrs Inflation attributes as specified in XML file. 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Newly created item. Return null for the default behavior. 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public T onCreateItem(String name, Context context, AttributeSet attrs); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class FactoryMerger<T> implements Factory<T> { 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Factory<T> mF1, mF2; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FactoryMerger(Factory<T> f1, Factory<T> f2) { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mF1 = f1; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mF2 = f2; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public T onCreateItem(String name, Context context, AttributeSet attrs) { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project T v = mF1.onCreateItem(name, context, attrs); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) return v; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mF2.onCreateItem(name, context, attrs); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new inflater instance associated with a 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * particular Context. 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context The Context in which this inflater will 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * create its items; most importantly, this supplies the theme 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from which the default values for their attributes are 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * retrieved. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected GenericInflater(Context context) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new inflater instance that is a copy of an 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * existing inflater, optionally with its Context 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * changed. For use in implementing {@link #cloneInContext}. 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param original The original inflater to copy. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newContext The new Context to use. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected GenericInflater(GenericInflater<T,P> original, Context newContext) { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = newContext; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactory = original.mFactory; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a copy of the existing inflater object, with the copy 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pointing to a different Context than the original. This is used by 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ContextThemeWrapper} to create a new inflater to go along 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with the new Context theme. 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newContext The new Context to associate with the new inflater. 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * May be the same as the original Context if desired. 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns a brand spanking new inflater object associated with 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the given Context. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13876f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne public abstract GenericInflater cloneInContext(Context newContext); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the default package that will be searched for classes to construct 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for tag names that have no explicit package. 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param defaultPackage The default package. This will be prepended to the 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * tag name, so it should end with a period. 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDefaultPackage(String defaultPackage) { 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultPackage = defaultPackage; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the default package, or null if it is not set. 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setDefaultPackage(String) 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The default package. 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getDefaultPackage() { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultPackage; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the context we are running in, for access to resources, class 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * loader, etc. 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Context getContext() { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mContext; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the current factory (or null). This is called on each element 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * name. If the factory returns an item, add that to the hierarchy. If it 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returns null, proceed to call onCreateItem(name). 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Factory<T> getFactory() { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFactory; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Attach a custom Factory interface for creating items while using this 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inflater. This must not be null, and can only be set 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * once; after setting, you can not change the factory. This is called on 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * each element name as the XML is parsed. If the factory returns an item, 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that is added to the hierarchy. If it returns null, the next factory 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default {@link #onCreateItem} method is called. 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If you have an existing inflater and want to add your 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * own factory to it, use {@link #cloneInContext} to clone the existing 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance and then you can use this function (once) on the returned new 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance. This will merge your own factory with whatever factory the 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * original instance is using. 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFactory(Factory<T> factory) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFactorySet) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("" + 1958a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock "A factory has already been set on this inflater"); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (factory == null) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new NullPointerException("Given factory can not be null"); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactorySet = true; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFactory == null) { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactory = factory; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactory = new FactoryMerger<T>(factory, mFactory); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inflate a new item hierarchy from the specified xml resource. Throws 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * InflaterException if there is an error. 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param resource ID for an XML resource to load (e.g., 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>R.layout.main_page</code>) 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param root Optional parent of the generated hierarchy. 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The root of the inflated hierarchy. If root was supplied, 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this is the root item; otherwise it is the root of the inflated 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * XML file. 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2207b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public T inflate(@XmlRes int resource, P root) { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return inflate(resource, root, root != null); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inflate a new hierarchy from the specified xml node. Throws 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * InflaterException if there is an error. * 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <em><strong>Important</strong></em> For performance 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * reasons, inflation relies heavily on pre-processing of XML files 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that is done at build time. Therefore, it is not currently possible to 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use inflater with an XmlPullParser over a plain XML file at runtime. 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parser XML dom node containing the description of the 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * hierarchy. 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param root Optional parent of the generated hierarchy. 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The root of the inflated hierarchy. If root was supplied, 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this is the that; otherwise it is the root of the inflated 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * XML file. 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public T inflate(XmlPullParser parser, P root) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return inflate(parser, root, root != null); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inflate a new hierarchy from the specified xml resource. Throws 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * InflaterException if there is an error. 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param resource ID for an XML resource to load (e.g., 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>R.layout.main_page</code>) 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param root Optional root to be the parent of the generated hierarchy (if 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <em>attachToRoot</em> is true), or else simply an object that 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provides a set of values for root of the returned 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * hierarchy (if <em>attachToRoot</em> is false.) 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param attachToRoot Whether the inflated hierarchy should be attached to 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the root parameter? 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The root of the inflated hierarchy. If root was supplied and 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attachToRoot is true, this is root; otherwise it is the root of 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the inflated XML file. 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2607b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public T inflate(@XmlRes int resource, P root, boolean attachToRoot) { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) System.out.println("INFLATING from resource: " + resource); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project XmlResourceParser parser = getContext().getResources().getXml(resource); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return inflate(parser, root, attachToRoot); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parser.close(); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inflate a new hierarchy from the specified XML node. Throws 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * InflaterException if there is an error. 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <em><strong>Important</strong></em> For performance 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * reasons, inflation relies heavily on pre-processing of XML files 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that is done at build time. Therefore, it is not currently possible to 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use inflater with an XmlPullParser over a plain XML file at runtime. 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parser XML dom node containing the description of the 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * hierarchy. 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param root Optional to be the parent of the generated hierarchy (if 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <em>attachToRoot</em> is true), or else simply an object that 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provides a set of values for root of the returned 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * hierarchy (if <em>attachToRoot</em> is false.) 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param attachToRoot Whether the inflated hierarchy should be attached to 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the root parameter? 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The root of the inflated hierarchy. If root was supplied and 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attachToRoot is true, this is root; otherwise it is the root of 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the inflated XML file. 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 29176f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne public T inflate(XmlPullParser parser, P root, 29276f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne boolean attachToRoot) { 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mConstructorArgs) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final AttributeSet attrs = Xml.asAttributeSet(parser); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConstructorArgs[0] = mContext; 29676f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne T result = (T) root; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Look for the root node. 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int type; 30176f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne while ((type = parser.next()) != parser.START_TAG 30276f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne && type != parser.END_DOCUMENT) { 30376f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne ; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30676f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne if (type != parser.START_TAG) { 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new InflateException(parser.getPositionDescription() 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": No start tag found!"); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("**************************"); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("Creating root: " 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + parser.getName()); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("**************************"); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Temp is the root that was found in the xml 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project T xmlRoot = createItemFromTag(parser, parser.getName(), 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project attrs); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32176f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne result = (T) onMergeRoots(root, attachToRoot, (P) xmlRoot); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("-----> start inflating children"); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inflate all children under temp 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rInflate(parser, result, attrs); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("-----> done inflating children"); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InflateException e) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (XmlPullParserException e) { 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project InflateException ex = new InflateException(e.getMessage()); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ex.initCause(e); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw ex; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project InflateException ex = new InflateException( 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parser.getPositionDescription() 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": " + e.getMessage()); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ex.initCause(e); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw ex; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34776f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne return result; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Low-level function for instantiating by name. This attempts to 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instantiate class of the given <var>name</var> found in this 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inflater's ClassLoader. 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * There are two things that can happen in an error case: either the 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * exception describing the error will be thrown, or a null will be 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returned. You must deal with both possibilities -- the former will happen 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the first time createItem() is called for a class of a particular name, 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the latter every time there-after for that class name. 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The full name of the class to be instantiated. 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param attrs The XML attributes supplied for this instance. 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 36676f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne * @return The newly instantied item, or null. 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final T createItem(String name, String prefix, AttributeSet attrs) 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws ClassNotFoundException, InflateException { 37076f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne Constructor constructor = (Constructor) sConstructorMap.get(name); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (null == constructor) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Class not found in the cache, see if it's real, 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and try to add it 37676f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne Class clazz = mContext.getClassLoader().loadClass( 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prefix != null ? (prefix + name) : name); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project constructor = clazz.getConstructor(mConstructorSignature); 379904de2ec9360de2ee54b91aaf9e141d9d8ab1de1Alan Viverette constructor.setAccessible(true); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sConstructorMap.put(name, constructor); 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] args = mConstructorArgs; 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args[1] = attrs; 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (T) constructor.newInstance(args); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NoSuchMethodException e) { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project InflateException ie = new InflateException(attrs 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getPositionDescription() 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": Error inflating class " 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + (prefix != null ? (prefix + name) : name)); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ie.initCause(e); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw ie; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ClassNotFoundException e) { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If loadClass fails, we should propagate the exception. 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project InflateException ie = new InflateException(attrs 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getPositionDescription() 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": Error inflating class " 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + constructor.getClass().getName()); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ie.initCause(e); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw ie; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This routine is responsible for creating the correct subclass of item 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * given the xml element name. Override it to handle custom item objects. If 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you override this in your subclass be sure to call through to 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * super.onCreateItem(name) for names you do not recognize. 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The fully qualified class name of the item to be create. 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param attrs An AttributeSet of attributes to apply to the item. 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The item created. 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected T onCreateItem(String name, AttributeSet attrs) throws ClassNotFoundException { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return createItem(name, mDefaultPackage, attrs); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final T createItemFromTag(XmlPullParser parser, String name, AttributeSet attrs) { 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) System.out.println("******** Creating item: " + name); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project T item = (mFactory == null) ? null : mFactory.onCreateItem(name, mContext, attrs); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item == null) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (-1 == name.indexOf('.')) { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item = onCreateItem(name, attrs); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item = createItem(name, null, attrs); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) System.out.println("Created item is: " + item); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return item; 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InflateException e) { 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ClassNotFoundException e) { 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project InflateException ie = new InflateException(attrs 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getPositionDescription() 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": Error inflating class " + name); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ie.initCause(e); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw ie; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project InflateException ie = new InflateException(attrs 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getPositionDescription() 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": Error inflating class " + name); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ie.initCause(e); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw ie; 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Recursive method used to descend down the xml hierarchy and instantiate 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * items, instantiate their children, and then call onFinishInflate(). 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 46276f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne private void rInflate(XmlPullParser parser, T parent, final AttributeSet attrs) 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int depth = parser.getDepth(); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int type; 46776f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne while (((type = parser.next()) != parser.END_TAG || 46876f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne parser.getDepth() > depth) && type != parser.END_DOCUMENT) { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47076f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne if (type != parser.START_TAG) { 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (onCreateCustomFromTag(parser, parent, attrs)) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("Now inflating tag: " + parser.getName()); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = parser.getName(); 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project T item = createItemFromTag(parser, name, attrs); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .println("Creating params from parent: " + parent); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 49076f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne ((P) parent).addItemFromInflater(item); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("-----> start inflating children"); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 49576f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne rInflate(parser, item, attrs); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println("-----> done inflating children"); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Before this inflater tries to create an item from the tag, this method 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be called. The parser will be pointing to the start of a tag, you 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * must stop parsing and return when you reach the end of this element! 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parser XML dom node containing the description of the hierarchy. 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent The item that should be the parent of whatever you create. 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param attrs An AttributeSet of attributes to apply to the item. 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether you created a custom object (true), or whether this 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inflater should proceed to create an item. 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 51476f0ce1fe4b10a67fb4c037a89024cc134ccb1c1Gilles Debunne protected boolean onCreateCustomFromTag(XmlPullParser parser, T parent, 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final AttributeSet attrs) throws XmlPullParserException { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected P onMergeRoots(P givenRoot, boolean attachToGivenRoot, P xmlRoot) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return xmlRoot; 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 523