在 setContentView() 之前调用 findViewById() 会导致 NullPointerException 但并非总是如此?
Calling findViewById() before setContentView() causes NullPointerException but not always?
好吧,当我调用 findViewById()
访问按钮时,我得到一个 NullPointerException
。我想我明白为什么我会收到这个错误,但是我脑子里有一些问题没有解决。
好吧,我想我收到这个错误是因为我将 findViewById()
调用从 onCreate()
方法内部移到了 class 范围,在所有方法之外。
现在我正在 onCreate()
方法之外初始化我的 Button
和 EditText
。
好吧,如果我理解正确的话,这是正在发生(空错误),因为 setContentView()
方法在 findViewById()
方法之后被调用,所以这就是它抛出异常的原因。
但是我不明白的是我在第二个 activity 中做了 同样的事情 并且工作了很好,没有任何空异常。我正在 onCreate()
方法之外初始化我的按钮等!
这确实让我有点困惑。如果能帮我解决这个问题,我将不胜感激。
第一个Activity
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();
}
});
}
第二个Activity
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);
//....
}
使用:
public class SecondActivity extends AppCompatActivity {
private Button signUpButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup)
signUpButton= findViewById(R.id.lo_signUpButton);
//...
}
}
在第二个 Activity 中,您正在做一些不同的事情:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
Button backButton = findViewById(R.id.su_backButton);
//...
}
这是正确的,因为您在 setContentView
调用后使用 findViewById
方法在 onCreate
中声明并初始化了 backButton
。
在第一个 Activity 中,您使用 signUpButton.setOnClickListener
设置侦听器,但 signUpButton
未初始化(因为它在 onCreate
方法之外)
同样在第二个 Activity 中,OnCreate
方法中未使用其他错误初始化的按钮。
第二个activity,你没有使用过初始化错误的按钮,一旦使用也会出现异常
您使用了正确初始化的 backButton。
答案很简单。全局变量在调用 setContentView() 之前进行初始化,这意味着 findViewById() 将 return 为空。 findViewById() return 如果找到或为空,则为视图。由于您还没有调用 setContentView,它找不到您想要的视图。
FirstActivity和SecondActivity中的全局变量都是null。
FirstActivity 和 SecondActivity 之间的区别在于,您不访问 SecondActivity 中的任何全局变量。
您在 SecondActivity 中使用的唯一视图是调用 setContentView 后检索到的 backButton,因此当然不会抛出 NullPointerException。
始终将变量声明为全局变量并在 onCreate() 中对其进行初始化。更好的是,尽量避免全局变量并通过方法参数传递它们。
好吧,当我调用 findViewById()
访问按钮时,我得到一个 NullPointerException
。我想我明白为什么我会收到这个错误,但是我脑子里有一些问题没有解决。
好吧,我想我收到这个错误是因为我将 findViewById()
调用从 onCreate()
方法内部移到了 class 范围,在所有方法之外。
现在我正在 onCreate()
方法之外初始化我的 Button
和 EditText
。
好吧,如果我理解正确的话,这是正在发生(空错误),因为 setContentView()
方法在 findViewById()
方法之后被调用,所以这就是它抛出异常的原因。
但是我不明白的是我在第二个 activity 中做了 同样的事情 并且工作了很好,没有任何空异常。我正在 onCreate()
方法之外初始化我的按钮等!
这确实让我有点困惑。如果能帮我解决这个问题,我将不胜感激。
第一个Activity
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();
}
});
}
第二个Activity
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);
//....
}
使用:
public class SecondActivity extends AppCompatActivity {
private Button signUpButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup)
signUpButton= findViewById(R.id.lo_signUpButton);
//...
}
}
在第二个 Activity 中,您正在做一些不同的事情:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
Button backButton = findViewById(R.id.su_backButton);
//...
}
这是正确的,因为您在 setContentView
调用后使用 findViewById
方法在 onCreate
中声明并初始化了 backButton
。
在第一个 Activity 中,您使用 signUpButton.setOnClickListener
设置侦听器,但 signUpButton
未初始化(因为它在 onCreate
方法之外)
同样在第二个 Activity 中,OnCreate
方法中未使用其他错误初始化的按钮。
第二个activity,你没有使用过初始化错误的按钮,一旦使用也会出现异常
您使用了正确初始化的 backButton。
答案很简单。全局变量在调用 setContentView() 之前进行初始化,这意味着 findViewById() 将 return 为空。 findViewById() return 如果找到或为空,则为视图。由于您还没有调用 setContentView,它找不到您想要的视图。
FirstActivity和SecondActivity中的全局变量都是null。 FirstActivity 和 SecondActivity 之间的区别在于,您不访问 SecondActivity 中的任何全局变量。
您在 SecondActivity 中使用的唯一视图是调用 setContentView 后检索到的 backButton,因此当然不会抛出 NullPointerException。
始终将变量声明为全局变量并在 onCreate() 中对其进行初始化。更好的是,尽量避免全局变量并通过方法参数传递它们。