Activity中View实例:全局持有还是每次调用findViewById?最佳实践
在包含大量View的Activity中的最佳实践
嘿,这个问题问得很到位!在处理这类有大量View的Activity时,咱们其实不用纠结于“全局实例VS重复findViewById”这两个选项,因为有更优雅高效的方案,同时也得避开这两种方式各自的坑:
先说说两种原始方式的问题
- 每次调用findViewById:这个方法本质是遍历整个View树去查找对应ID的控件,频繁调用会带来不必要的性能开销,而且代码里到处都是findViewById,既冗余又不好维护。
- 声明public全局View实例:把View设为public会直接破坏类的封装性,外部代码可以随意修改这个View的状态,很容易埋下难以追踪的bug;另外如果处理不当,还可能因为持有View引用导致Activity内存泄漏。
推荐的最佳实践
1. 优先使用View Binding(AndroidX官方推荐)
这是目前最省心的方案,Android Studio会根据你的布局文件自动生成对应的Binding类,帮你省去所有findViewById的代码,而且是类型安全的,还能避免空指针异常。
举个例子:
public class AskActivity extends Activity { private ActivityAskBinding binding; // 自动生成的Binding类 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityAskBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); // 直接通过binding获取View,不用再写findViewById binding.question_edit.setText("Hello View Binding!"); } }
2. 老项目可以用ButterKnife(注解框架)
如果你的项目还没迁移到AndroidX或者暂时不想用View Binding,ButterKnife是个不错的替代方案,通过注解来绑定View,减少模板代码:
public class AskActivity extends Activity { @BindView(R.id.question_edit) private EditText question_edit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ask); ButterKnife.bind(this); // 直接使用question_edit即可 question_edit.setText("Hello ButterKnife!"); } }
3. 必须用findViewById的情况:存为私有成员变量
如果以上两种都用不了,那正确的做法是在onCreate里调用一次findViewById,把结果存为私有成员变量,而不是public全局变量。这样既复用了实例,又保证了类的封装性:
public class AskActivity extends Activity { private EditText question_edit; // 私有成员,仅内部使用 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ask); question_edit = findViewById(R.id.question_edit); // 后续直接使用question_edit question_edit.setHint("请输入问题"); } }
总结
优先级排序是:View Binding > 注解框架(如ButterKnife) > 私有成员变量存储findViewById结果,绝对不要选public全局变量或者重复调用findViewById的方式。
内容的提问来源于stack exchange,提问作者sisho
相关产品推荐
相关产品推荐

