GenericInflaterpublic abstract class GenericInflater extends Object Generic XML inflater. This has been adapted from {@link LayoutInflater} and
quickly passed over to use generics. |
Fields Summary |
---|
private final boolean | DEBUG | protected final android.content.Context | mContext | private boolean | mFactorySet | private Factory | mFactory | private final Object[] | mConstructorArgs | private static final Class[] | mConstructorSignature | private static final HashMap | sConstructorMap | private String | mDefaultPackage |
Constructors Summary |
---|
protected GenericInflater(android.content.Context context)Create a new inflater instance associated with a
particular Context.
mContext = context;
| protected GenericInflater(GenericInflater original, android.content.Context newContext)Create a new inflater instance that is a copy of an
existing inflater, optionally with its Context
changed. For use in implementing {@link #cloneInContext}.
mContext = newContext;
mFactory = original.mFactory;
|
Methods Summary |
---|
public abstract android.preference.GenericInflater | cloneInContext(android.content.Context newContext)Create a copy of the existing inflater object, with the copy
pointing to a different Context than the original. This is used by
{@link ContextThemeWrapper} to create a new inflater to go along
with the new Context theme.
| public final T | createItem(java.lang.String name, java.lang.String prefix, android.util.AttributeSet attrs)Low-level function for instantiating by name. This attempts to
instantiate class of the given name found in this
inflater's ClassLoader.
There are two things that can happen in an error case: either the
exception describing the error will be thrown, or a null will be
returned. You must deal with both possibilities -- the former will happen
the first time createItem() is called for a class of a particular name,
the latter every time there-after for that class name.
Constructor constructor = (Constructor) sConstructorMap.get(name);
try {
if (null == constructor) {
// Class not found in the cache, see if it's real,
// and try to add it
Class clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name);
constructor = clazz.getConstructor(mConstructorSignature);
sConstructorMap.put(name, constructor);
}
Object[] args = mConstructorArgs;
args[1] = attrs;
return (T) constructor.newInstance(args);
} catch (NoSuchMethodException e) {
InflateException ie = new InflateException(attrs
.getPositionDescription()
+ ": Error inflating class "
+ (prefix != null ? (prefix + name) : name));
ie.initCause(e);
throw ie;
} catch (ClassNotFoundException e) {
// If loadClass fails, we should propagate the exception.
throw e;
} catch (Exception e) {
InflateException ie = new InflateException(attrs
.getPositionDescription()
+ ": Error inflating class "
+ constructor.getClass().getName());
ie.initCause(e);
throw ie;
}
| private final T | createItemFromTag(org.xmlpull.v1.XmlPullParser parser, java.lang.String name, android.util.AttributeSet attrs)
if (DEBUG) System.out.println("******** Creating item: " + name);
try {
T item = (mFactory == null) ? null : mFactory.onCreateItem(name, mContext, attrs);
if (item == null) {
if (-1 == name.indexOf('.")) {
item = onCreateItem(name, attrs);
} else {
item = createItem(name, null, attrs);
}
}
if (DEBUG) System.out.println("Created item is: " + item);
return item;
} catch (InflateException e) {
throw e;
} catch (ClassNotFoundException e) {
InflateException ie = new InflateException(attrs
.getPositionDescription()
+ ": Error inflating class " + name);
ie.initCause(e);
throw ie;
} catch (Exception e) {
InflateException ie = new InflateException(attrs
.getPositionDescription()
+ ": Error inflating class " + name);
ie.initCause(e);
throw ie;
}
| public android.content.Context | getContext()Return the context we are running in, for access to resources, class
loader, etc.
return mContext;
| public java.lang.String | getDefaultPackage()Returns the default package, or null if it is not set.
return mDefaultPackage;
| public final android.preference.GenericInflater$Factory | getFactory()Return the current factory (or null). This is called on each element
name. If the factory returns an item, add that to the hierarchy. If it
returns null, proceed to call onCreateItem(name).
return mFactory;
| public T | inflate(org.xmlpull.v1.XmlPullParser parser, P root)Inflate a new hierarchy from the specified xml node. Throws
InflaterException if there is an error. *
Important For performance
reasons, inflation relies heavily on pre-processing of XML files
that is done at build time. Therefore, it is not currently possible to
use inflater with an XmlPullParser over a plain XML file at runtime.
return inflate(parser, root, root != null);
| public T | inflate(int resource, P root, boolean attachToRoot)Inflate a new hierarchy from the specified xml resource. Throws
InflaterException if there is an error.
if (DEBUG) System.out.println("INFLATING from resource: " + resource);
XmlResourceParser parser = getContext().getResources().getXml(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
| public T | inflate(org.xmlpull.v1.XmlPullParser parser, P root, boolean attachToRoot)Inflate a new hierarchy from the specified XML node. Throws
InflaterException if there is an error.
Important For performance
reasons, inflation relies heavily on pre-processing of XML files
that is done at build time. Therefore, it is not currently possible to
use inflater with an XmlPullParser over a plain XML file at runtime.
synchronized (mConstructorArgs) {
final AttributeSet attrs = Xml.asAttributeSet(parser);
mConstructorArgs[0] = mContext;
T result = (T) root;
try {
// Look for the root node.
int type;
while ((type = parser.next()) != parser.START_TAG
&& type != parser.END_DOCUMENT) {
;
}
if (type != parser.START_TAG) {
throw new InflateException(parser.getPositionDescription()
+ ": No start tag found!");
}
if (DEBUG) {
System.out.println("**************************");
System.out.println("Creating root: "
+ parser.getName());
System.out.println("**************************");
}
// Temp is the root that was found in the xml
T xmlRoot = createItemFromTag(parser, parser.getName(),
attrs);
result = (T) onMergeRoots(root, attachToRoot, (P) xmlRoot);
if (DEBUG) {
System.out.println("-----> start inflating children");
}
// Inflate all children under temp
rInflate(parser, result, attrs);
if (DEBUG) {
System.out.println("-----> done inflating children");
}
} catch (InflateException e) {
throw e;
} catch (XmlPullParserException e) {
InflateException ex = new InflateException(e.getMessage());
ex.initCause(e);
throw ex;
} catch (IOException e) {
InflateException ex = new InflateException(
parser.getPositionDescription()
+ ": " + e.getMessage());
ex.initCause(e);
throw ex;
}
return result;
}
| public T | inflate(int resource, P root)Inflate a new item hierarchy from the specified xml resource. Throws
InflaterException if there is an error.
return inflate(resource, root, root != null);
| protected boolean | onCreateCustomFromTag(org.xmlpull.v1.XmlPullParser parser, T parent, android.util.AttributeSet attrs)Before this inflater tries to create an item from the tag, this method
will be called. The parser will be pointing to the start of a tag, you
must stop parsing and return when you reach the end of this element!
return false;
| protected T | onCreateItem(java.lang.String name, android.util.AttributeSet attrs)This routine is responsible for creating the correct subclass of item
given the xml element name. Override it to handle custom item objects. If
you override this in your subclass be sure to call through to
super.onCreateItem(name) for names you do not recognize.
return createItem(name, mDefaultPackage, attrs);
| protected P | onMergeRoots(P givenRoot, boolean attachToGivenRoot, P xmlRoot)
return xmlRoot;
| private void | rInflate(org.xmlpull.v1.XmlPullParser parser, T parent, android.util.AttributeSet attrs)Recursive method used to descend down the xml hierarchy and instantiate
items, instantiate their children, and then call onFinishInflate().
final int depth = parser.getDepth();
int type;
while (((type = parser.next()) != parser.END_TAG ||
parser.getDepth() > depth) && type != parser.END_DOCUMENT) {
if (type != parser.START_TAG) {
continue;
}
if (onCreateCustomFromTag(parser, parent, attrs)) {
continue;
}
if (DEBUG) {
System.out.println("Now inflating tag: " + parser.getName());
}
String name = parser.getName();
T item = createItemFromTag(parser, name, attrs);
if (DEBUG) {
System.out
.println("Creating params from parent: " + parent);
}
((P) parent).addItemFromInflater(item);
if (DEBUG) {
System.out.println("-----> start inflating children");
}
rInflate(parser, item, attrs);
if (DEBUG) {
System.out.println("-----> done inflating children");
}
}
| public void | setDefaultPackage(java.lang.String defaultPackage)Sets the default package that will be searched for classes to construct
for tag names that have no explicit package.
mDefaultPackage = defaultPackage;
| public void | setFactory(android.preference.GenericInflater$Factory factory)Attach a custom Factory interface for creating items while using this
inflater. This must not be null, and can only be set
once; after setting, you can not change the factory. This is called on
each element name as the XML is parsed. If the factory returns an item,
that is added to the hierarchy. If it returns null, the next factory
default {@link #onCreateItem} method is called.
If you have an existing inflater and want to add your
own factory to it, use {@link #cloneInContext} to clone the existing
instance and then you can use this function (once) on the returned new
instance. This will merge your own factory with whatever factory the
original instance is using.
if (mFactorySet) {
throw new IllegalStateException("" +
"A factory has already been set on this inflater");
}
if (factory == null) {
throw new NullPointerException("Given factory can not be null");
}
mFactorySet = true;
if (mFactory == null) {
mFactory = factory;
} else {
mFactory = new FactoryMerger<T>(factory, mFactory);
}
|
|