从下边的代码说起,这个是我们在Activity里写的最多的代码之一,我们接下来看下这个方法接下来是怎么处理的
textView= (TextView) findViewById(R.id.textView);
在Activity中的调用如下:
public View findViewById(int id) {
return getWindow().findViewById(id);
}
getWindow()在Activity中实际是PhoneWindow(com.android.internal.policy.impl.PhoneWindow)对象,因此接下来看下PhoneWindow中findViewById()是如何实现的,PhoneWindow实现继承来自Window,所以具体代码在Window类中,Window中实现如下:
public View findViewById(int id) {
return getDecorView().findViewById(id);
}
getDecorView()返回的是DecorView对象,我们来看下DecorView(PhoneWindow的内部类)对象:
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker
DecorView也没有什么神秘之处,继承自FrameLayout,findViewById方法也是由父类继承而来,所以绕了一圈这个findViewById方法绕回了我们熟悉的View和Vie wGroup中,所以我们看下View和ViewGroup实现也就知道了这个方法的具体实现了,首先看View:
//主要是两个方法,不通版本源码略有差异
public final View findViewById(int id) {
if (id < 0) {
return null;
}
return findViewTraversal(id);
}
protected View findViewTraversal(int id) {
if (id == mID) {
return this;
}
return null;
}
View的实现比较简单,主要就是在调用findViewbyId时,看下这个id是不是跟自己的id相同,如果相同就返回自己,如果不同,就返回null。接下来看下ViewGroup的实现:
//ViewGroup 主要复写了findViewTraversal方法
@Override
protected View findViewTraversal(int id) {
if (id == mID) {
return this;
}
final View[] where = mChildren;
final int len = mChildrenCount;
for (int i = 0; i < len; i++) {
View v = where[i];
if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewById(id);
if (v != null) {
return v;
}
}
}
return null;
}
基本实现就是遍历自己的子View,然后调用子View的findViewById, 如果子View中找到了就返回了,如果子View是ViewGroup,子ViewGroup也会自动找子,这样实现了整个View树的查找。
------------分割线--------------
总结下来便是findViewById()方法,最终是调用到了Activity内部这个DecorView的方法,由它来遍历下边View树中相同id的View返回。至于这个id是怎么来的后续有时间再写篇文章。