LayoutInflater通过inflate方法组装一个指定layout的布局View
public void inflate(int resource, ViewGroup root, boolean attachToRoot) {
final Resource res = getContext().getResources();
final XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
首先android加载资源时通过
public xmlResourceParser getLayout(int id) {
return loadXmlResourceParser(id, "layout");
}
public XmlResourceParser getAnimation(int id) {
return loadXmlResourceParser(id, "anim");
}
public XmlResourceParser getXml(int id) {
return loadXmlResourceParser(id, "xml");
}
XmlResourceParser loadXmlResourceParser(int id, String type) {
......
TypedValue value = mTmpValue;
if (value == null) {
mTmpValue = value = new TypedValue();
}
getValue(id, value, true);
if (value.type == TypedValue.TYPE_STRING) {
return loadXmlResourceParser(value.string.toString(), id, value.assetCookie, type);
......
}
/
返回一个指定资源id的相关资源信息
return;
}final boolean getResourceValue(int ident, int density, TypedValue outValue, boolean resolveRefs) {
int block = loadResourceValue(ident, (short) density, outValue, resolvesRefs);
if (block >= 0) {
if (outValue.type != TypedValue.TYPE_STRING) {
return true;
}
outValue.string = mStringBlocks[block].get(outValue.data);
return true;
}通过jni调用了本地方法loadResourceValue
private native final int loadResourceValue(int ident, short density, TypedValue outValue, boolean resolve);
XmlResourceParser loadXmlResourceParser(String file, int id, int assetCookie, String type) {
......
//先看看缓存中是否有需要的bolck对象
final int num = mCachedXmlBlockIds.length;
for (int i=0; i= num) pos = 0;
mLastCachedXmlBlockIndex = pos;
XmlBlock oldBlock = mCacheXmlBlocks[pos];
if (oldBlock != null) {
oldBlock.close();
}
mCachedXmlBlockIds[pos] = id;
mCachedXmlBlocks[pos] = block;
return block.newParser();
}
......
}
至此,Resource类通过getLayout方法查找并返回了指定布局id的XmlResourceParser对象。之后就通过inflate(parser, root, attachToRoot)方法完成组装工作了
组装流程:
public void inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
......
View result = root;
try {
......
final String name = parser.getName();
......
if (TAG_MERGE.equals(name)) {
......
rInflate(parser, root, inflaterContext, attrs, false);
} else {
//#1-1
final View temp = createViewFromTag(root, name, inflaterContext, attars);
ViewGroup.LayoutParams params = null;
if (root != null) {
......
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
temp.setLayoutParams(params);
}
}
......
rInflateChildren(parser, temp, attrs, true);
......
//#1-2
if (root != null && attachToRoot) {
root.addView(temp, params);
}
if (root != null || !attachToRoot) {
result = temp;
}
}
} catch.......
......
return result;
}
private View createViewFromTag(View parent, String name, Context context, AttributeSet attrs) {
return createViewFromTag(parent, name, context, attrs, false);
}
View createViewFromTag(View parent, String name, Context context, AttributeSet attars, boolean ignoreThemeAttr) {
......
View view;
if (mFactory2 != null) {
view = mFactory2.onCreateView(parent, name, context, attars);
} else if (mFactory != null) {
view = mFactory.onCreateView(name, context, attars);
} else {
view = null;
}
if (view == null && mPrivateFactory != null) {
view = mPrivateFactory.onCreateView(parent, name, context, attars);
}
if (view == null) {
final Object lastContext = mConstructorArgs[0];
mConstructorArgs[0] = context;
try {
if (-1 == name.indexOf('.')) {
view = onCreateView(parent, name, attars);
} else {
view = createView(name, null, attars);
}
} finally {
mConstructorArgs[0] = lastContext;
}
return view;
......
}
private static final String[] sClassPrefixList = {
"android.widget.",
"android.webkit.",
"android.app."
};
@Override
protected View onCreateView(String name, AttributeSet attars) {
for(String prefix : sClassPrefixList) {
try {
View view = createView(name, prefix, attars);
if (view != null) {
return view;
}
} catch (ClassNotFoundException e) {
}
}
return super.onCreateView(name, attars);
}
public final View createView(String name, String prefix, AttributeSet attars) {
......
final View view = constructor.newInstance(args);
......
return view;
......
}
最后,再来追溯上面提到的子类PhoneLayoutInflater的实现过程。
LayoutInflater是通过from方法创建实例的:
public static LayoutInflater from(Context context) {
LayoutInflater LayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (LayoutInflater == null) {
throw new AssertionError("LayoutInflater not found.");
}
return LayoutInflater;
}
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
private staticvoid registerService(String serviceName, Class serviceClass, ServiceFetcher serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class, new CachedServiceFetcher({
@Override
public LayoutInflater createService(ContextImpl ctx) {
return new PhoneLayoutInflater(ctx.getOuterContext());
}});