- 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.3 onCreateView 和 createView 方法解析
onCreateView 有两个重载方法,最终调用的是 createView(String name, String prefix, AttributeSet attrs) 。
createView 主要做的操作有:
- 先通过 Filter,看是否过滤。
- 利用反射实例化 View 对象。
源码分析:
protected View onCreateView(View parent, String name, AttributeSet attrs)
throws ClassNotFoundException {
return onCreateView(name, attrs);
}
protected View onCreateView(String name, AttributeSet attrs)
throws ClassNotFoundException {
// 系统控件,前缀自动补上"android.view."
return createView(name, "android.view.", attrs);
}
public final View createView(String name, String prefix, AttributeSet attrs)
throws ClassNotFoundException, InflateException {
// 通过以 View 的 name 为 key,查询构造函数的缓存 map 中时候已经有该 View 的构造函数。
Constructor<? extends View> constructor = sConstructorMap.get(name);
Class<? extends View> clazz = null;
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, name);
// 构造函数在缓存的 map 中没有,则尝试去创建并添加。
if (constructor == null) {
// 通过 类名去加载控件的字节码
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name).asSubclass(View.class);
//如果有自定义的过滤器并且加载到字节码,则通过过滤器判断是否允许加载该 View。
if (mFilter != null && clazz != null) {
boolean allowed = mFilter.onLoadClass(clazz);
if (!allowed) {
// 如果不允许则抛出异常。
failNotAllowed(name, prefix, attrs);
}
}
// 得到构造函数
constructor = clazz.getConstructor(mConstructorSignature);
constructor.setAccessible(true);
// 缓存构造函数
sConstructorMap.put(name, constructor);
} else {
// setFilter() 可能会在类的构造函数被添加到 map 之后,所以获取到 map 中的构造函数后还需要判断是否过滤。
if (mFilter != null) {
// 过滤的 map 中是否已经包含了此类名。
Boolean allowedState = mFilterMap.get(name);
// 当前类名没有被放到过滤的缓存 map 中
if (allowedState == null) {
// 重新加载类的字节码
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name).asSubclass(View.class);
// 重新通过过滤器判断是否过滤。
boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
// 把过滤结果放到过滤的缓存 map 中。
mFilterMap.put(name, allowed);
if (!allowed) {
// 如果要过滤,则抛出异常。
failNotAllowed(name, prefix, attrs);
}
} else if (allowedState.equals(Boolean.FALSE)) {
// 缓存构造函数的 map 中已经保存了当前要实例化的 View 的构造函数并且是要过滤的,抛出异常。
failNotAllowed(name, prefix, attrs);
}
}
}
// 实例化类的参数数组,0 是获取 LayoutInflater 传入的 Context,1 是 View 的属性
Object[] args = mConstructorArgs;
args[1] = attrs;
// 通过构造函数实例化 View(看到此行就知道,为什么自定义 View 或者 ViewGroup 的时候,如果在布局中使用的话,必须重写两个参数的构造函数了。)
final View view = constructor.newInstance(args);
// 如果当前 View 是 ViewStub,则把布局填充器设置给它。(因为 ViewStub 在此刻并不会填充期子 View,而是等需要的时候由用户手动触发。)
if (view instanceof ViewStub) {
// 把当前 LayoutInflater 的克隆传递给 ViewStub,让 ViewStub 实例化的时候用,因为 ViewStub 只是在需要的时候才会实例化 View。
final ViewStub viewStub = (ViewStub) view;
viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
}
return view;
} catch (NoSuchMethodException e) {
InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Error inflating class "
+ (prefix != null ? (prefix + name) : name));
ie.initCause(e);
throw ie;
} catch (ClassCastException e) {
// If loaded class is not a View subclass
InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Class is not a View "
+ (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 "
+ (clazz == null ? "<unknown>" : clazz.getName()));
ie.initCause(e);
throw ie;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论