- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
5.1 inflate 方法解析
inflate 方法主要是把布局资源实例化成 View 并返回。
通过 获取 LayoutInflater 的三种方式 我们知道,通过布局文件填充成 View 对象最终调用的是下面两个方法:
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
if (DEBUG) System.out.println("INFLATING from resource: " + resource);
//获取布局资源的 xml 解析器,注意:在开头的时候我们强调过,普通的 xml 是不被支持的,必须是经过编译器处理过的。
XmlResourceParser parser = getContext().getResources().getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
} 最终调用的是此方法:
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
// from 传入的 Context
final Context inflaterContext = mContext;
// 判断 parser 是否是 AttributeSet,如果不是则用 XmlPullAttributes 去包装一下。
final AttributeSet attrs = Xml.asAttributeSet(parser);
// 保存之前的 Context
Context lastContext = (Context) mConstructorArgs[0];
// 赋值为传入的 Context
mConstructorArgs[0] = inflaterContext;
// 默认返回的是传入的 Parent
View result = root;
try {
// 查找开始标签
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty
}
//如果没找到有效的开始标签则抛出 InflateException
if (type != XmlPullParser.START_TAG) {
throw new InflateException(parser.getPositionDescription()
+ ": No start tag found!");
}
//获取控件的名称
final String name = parser.getName();
if (DEBUG) {
System.out.println("**************************");
System.out.println("Creating root view: "
+ name);
System.out.println("**************************");
}
// 如果根节点是“merge”标签
if (TAG_MERGE.equals(name)) {
// 根节点为空或者不添加到根节点上,则抛出异常。
// 因为“merge”标签必须是要被添加到父节点上的,不能独立存在。
if (root == null || !attachToRoot) {
throw new InflateException("<merge /> can be used only with a valid "
+ "ViewGroup root and attachToRoot=true");
}
// 递归实例化 root(也就是传入 Parent)下所有的 View
rInflate(parser, root, inflaterContext, attrs, false);
} else {
// temp 是当前 xml 的根节点的 View。通过父 View、View 名、Context、属性,来实例化 View。也即实例化根节点的 View。
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
ViewGroup.LayoutParams params = null;
// 如果传入 Parent 不为空
if (root != null) {
if (DEBUG) {
System.out.println("Creating params from root: " +
root);
}
// 创建父 View 类型的 LayoutParams 参数
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// 如果不把填充的 View 关联在父 View 上,则把父 View 的 LayoutParams 参数设置给它
// 如果把填充的 View 关联在父 View 上,则会走下面 addView 的逻辑
temp.setLayoutParams(params);
}
}
if (DEBUG) {
System.out.println("-----> start inflating children");
}
// 实例化根节点 View 下面的所有子 View。
// TODO ..................
rInflate(parser, temp, attrs, true);
if (DEBUG) {
System.out.println("-----> done inflating children");
}
// Google 建议关联所有找到的 View
// 如果根节点不为 null,并且需要把根节点 View 关联到 Parent 上,则使用 addView 方法把布局填充成的 View 树添加到 Parent 上。
if (root != null && attachToRoot) {
root.addView(temp, params);
}
// 决定返回的 RootView(也即传入的 Parent)还是 xml 中的根节点的 View。
// 如果传入的 Parent 为空 或 实例化的 View 不添加到 Parent 上,则返回布局文件的根节点的 View
// 否则,返回 Parent
if (root == null || !attachToRoot) {
result = temp;
}
}
} 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;
} finally {
// Don't retain static reference on context.
// 把这之前保存的 Context 从新放回全局变量中。
mConstructorArgs[0] = lastContext;
mConstructorArgs[1] = null;
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
return result;
}
}绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论