为何无法在Android的onCreate方法外初始化EditText与Button?
好问题!这其实和Android Activity的生命周期逻辑直接相关,咱们来一步步理清楚:
先看两段代码的核心差异
第一段(无法正常运行)
public class MainActivity extends AppCompatActivity { public static final String NAME = "android.example.br.CUSTOM_INTENT"; EditText edt = (EditText)findViewById(R.id.editText); Button btn = (Button)findViewById(R.id.button2); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
第二段(可正常运行)
public class MainActivity extends AppCompatActivity { public static final String NAME = "android.example.br.CUSTOM_INTENT"; EditText edt; Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button)findViewById(R.id.button2); edt = (EditText)findViewById(R.id.editText); } }
问题的根源:Activity生命周期与布局加载时机
说白了,控件的实例化依赖于布局文件的加载,而布局文件是在onCreate方法里通过setContentView(R.layout.activity_main)才加载到Activity中的。
- 在第一段代码里,你直接在类的成员变量位置调用
findViewById,这时候Activity还没走到onCreate方法,布局文件根本没被加载,系统找不到对应的控件ID,所以findViewById会返回null。后续如果对这些null的控件做操作(比如设置点击事件、获取输入内容),就会直接抛出空指针异常,导致代码无法正常运行。 - 第二段代码则是先声明了控件的引用(只是占个位置,不初始化),等到
onCreate方法里执行完setContentView,布局已经加载完成、控件已经被系统实例化之后,再调用findViewById去获取控件的真实实例,这时候自然就能拿到正确的对象,代码也就可以正常运行了。
总结一下
所有布局内的控件,必须在Activity完成布局加载之后才能被获取到。onCreate是Android系统给我们的第一个可以安全加载布局并初始化控件的生命周期回调方法,除此之外,像onStart、onResume这些后续的生命周期方法也可以,但通常我们都会选择在onCreate里完成控件初始化,这是最规范的做法。
内容的提问来源于stack exchange,提问作者吳柏亞
相关产品推荐
相关产品推荐

