Android 在setContentView()之前调用findViewById()会导致NullPointerException,但并不总是这样?
当我调用Android 在setContentView()之前调用findViewById()会导致NullPointerException,但并不总是这样?,android,nullpointerexception,findviewbyid,setcontentview,Android,Nullpointerexception,Findviewbyid,Setcontentview,当我调用findViewById()访问按钮时,我会得到一个NullPointerException。我想我明白为什么我会犯这个错误,但我脑子里有些问题还没有解决。 我想我得到这个错误是因为我将findViewById()调用从onCreate()方法内部移到了类范围之外,移到了所有方法之外 因此,现在我正在初始化按钮和编辑文本方法之外的onCreate()方法。 如果我理解正确,这会发生(Null错误),因为setContentView()方法在findViewById()方法之后调用,所以它
findViewById()
访问按钮时,我会得到一个NullPointerException
。我想我明白为什么我会犯这个错误,但我脑子里有些问题还没有解决。
我想我得到这个错误是因为我将findViewById()
调用从onCreate()
方法内部移到了类范围之外,移到了所有方法之外
因此,现在我正在初始化按钮和编辑文本方法之外的onCreate()
方法。
如果我理解正确,这会发生(Null错误),因为setContentView()
方法在findViewById()
方法之后调用,所以它会引发异常
但是我不明白的是,我在第二次活动中做了同样的事情,并且工作得很好,没有任何异常。我正在初始化onCreate()方法之外的按钮等
这确实让我有点困惑。如果能帮我解决这个问题,我将不胜感激
第一项活动
public class FirstActivity extends AppCompatActivity {
private Button signUpButton= findViewById(R.id.lo_signUpButton);
private Button loginButton = findViewById(R.id.lo_loginButton);
private EditText username= findViewById(R.id.lo_usernameText);
private EditText password= findViewById(R.id.lo_passwordText);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_login);
Log.i(TAG,"Create "+formatter.format(new Date()));
//listeners
signUpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(LoginActivity.this, SignUpActivity.class));
finish();
}
});
}
public class SecondActivity extends AppCompatActivity {
private EditText username = findViewById(R.id.su_username);
private EditText password = findViewById(R.id.su_password);
private TextView errorText= findViewById(R.id.su_error_msg);
private Button signUpButton=findViewById(R.id.su_signupButton);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup);
Log.i(TAG,"Create");
//listeners
Button backButton = findViewById(R.id.su_backButton);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(SignUpActivity.this, LoginActivity.class));
Log.i(TAG,"Going Back ");
finish();
}
});
第二项活动
public class FirstActivity extends AppCompatActivity {
private Button signUpButton= findViewById(R.id.lo_signUpButton);
private Button loginButton = findViewById(R.id.lo_loginButton);
private EditText username= findViewById(R.id.lo_usernameText);
private EditText password= findViewById(R.id.lo_passwordText);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_login);
Log.i(TAG,"Create "+formatter.format(new Date()));
//listeners
signUpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(LoginActivity.this, SignUpActivity.class));
finish();
}
});
}
public class SecondActivity extends AppCompatActivity {
private EditText username = findViewById(R.id.su_username);
private EditText password = findViewById(R.id.su_password);
private TextView errorText= findViewById(R.id.su_error_msg);
private Button signUpButton=findViewById(R.id.su_signupButton);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup);
Log.i(TAG,"Create");
//listeners
Button backButton = findViewById(R.id.su_backButton);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(SignUpActivity.this, LoginActivity.class));
Log.i(TAG,"Going Back ");
finish();
}
});
不能使用此初始化:
public class SecondActivity extends AppCompatActivity {
private Button signUpButton= findViewById(R.id.lo_signUpButton);
//....
}
使用:
在第二个活动中,您正在做一些不同的事情:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
Button backButton = findViewById(R.id.su_backButton);
//...
}
这是正确的,因为在调用setContentView
之后,您在onCreate
中使用findViewById
方法声明和初始化backButton
在第一个活动中,您使用signUpButton.setOnClickListener
设置侦听器,但是signUpButton
未初始化(因为它在onCreate
方法之外)
另外,在第二个活动中,OnCreate
方法中没有使用初始化错误的其他按钮。在第二个活动中,您没有使用初始化错误的按钮,一旦使用它们,也会导致异常
您使用了正确初始化的backButton。答案非常简单。全局变量在调用setContentView()之前初始化,这意味着findViewById()将返回null。findViewById()在找到或为null时返回视图。由于您尚未调用setContentView,因此它无法找到所需的视图
FirstActivity和SecondActivity中的全局变量均为null。
FirstActivity和SecondActivity的区别在于,您不访问SecondActivity中的任何全局变量
在SecondActivity中使用的唯一视图是backButton,它是在调用setContentView后检索到的,因此当然不会引发NullPointerException
始终将变量声明为全局变量,并在onCreate()中初始化它。更好的是,尽量避免使用全局变量,并通过方法参数传递它们。好的,我也是这么认为的。但是为什么我的第二个活动没有引起任何异常?两者都进行相同的初始化…@Panagiss,因为在第二个活动中您使用的是不同的东西:Button backButton=findViewById(R.id.su_backButton)代码>而不是signUpButton.setOnClickListener(新视图.OnClickListener()
@Panagiss我已经更新了答案。在第一个活动中,您正在使用signUpButton设置侦听器。setOnClickListener
但是signUpButton
未初始化。在第二个活动中,您在设置侦听器之前正确使用findViewById
。在OnCreate
方法。非常感谢!!调用findViewById()
字段初始值设定项中的字段总是会崩溃。您可能查看了错误的代码,或者运行了过时的生成,或者其他原因。所有给出的答案都是错误的。这与您稍后设置侦听器或以其他方式访问这些字段无关。第一个findViewById()
调用将立即抛出,远远早于onCreate()
运行。