自打学习Android开发以来,findViewById就是我使用最频繁的函数之一。findViewById可为灵活至极,但是又让人爱恨交加。那findViewById究竟有哪些优缺点,他又有哪些替代方案呢?今天就来做一个总结
findViewById
findViewById的原理
findViewById的原理非常简单,我们都知道Android中的View结构是一个树形结构,findViewById就是自树的根节点,依次遍历其子节点,知道找到目标的id。
findViewById的优点
还是先夸夸findViewById的优点吧,
- 兼容性好,下面各种替代方案,都有其适用的场景,但是findViewById适用所有的场景,当你不知道用哪种方案的时候,那就用findViewById吧,肯定没有错。
- 非常灵活,适合动态加载layout文件。比如一个Activity,需要在不同的业务中,加载两个不同的layout文件,但是两个layout文件只有部分间距不同,其他各个元素都是相同的。这个时候,用findViewId就可以完美适用。
findViewById的缺点
- 性能略差不好,findViewById是基于树形结构的查找,理论上会带来性能的额外开销,但是实际项目中,因为控件的个数也不会非常非常多,所以可以忽略不计。;
- Fragment中使用容易犯错。从原理图可以看到,在Activity中调用findViewById,实际上是调用Window中的findViewById,但是Fragment中并没有单独的Window,Fragment中调用findViewById的效果和Activity中调用的效果一模一样。所以如果一个Activity中有多个Fragment,Fragment中的控件名称又有重复的,那直接findViewById会出错的;
- 增加代码的耦合度,findViewById随时实地都可以调用,在子view中,在Activity中等等,如果滥用起来,会让代码耦合的一塌糊涂,后面查找bug起来,非常麻烦,因为不知道View的属性在哪个类中被改变了;
- 容易引发空指针,一个大型项目中,控件的id经常会重复,xml中删除了一个控件,但是对应的Activity中没有删除这个控件的相关引用,编译时并不会报错,但是运营室时会报出空指针;
- 代码可读性不好,findViewById往往在Activity的onCreate方法中被引用,我们不能方便的将xml中的控件与代码中的控件结合起来,特别是如果xml的命名与代码中的命名又不规范,代码阅读起来简直就是噩梦。
ButterKnife
有人推出了ButterKnife框架,详细的用法不啰嗦了,简单看下使用方法
class ExampleActivity extends Activity {
@BindView(R.id.title) TextView title;
@BindView(R.id.subtitle) TextView subtitle;
@BindView(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...