在 setContentView() 之前调用 findViewById() 会导致 NullPointerException 但并非总是如此? [复制]
Posted
技术标签:
【中文标题】在 setContentView() 之前调用 findViewById() 会导致 NullPointerException 但并非总是如此? [复制]【英文标题】:Calling findViewById() before setContentView() causes NullPointerException but not always? [duplicate] 【发布时间】:2020-12-28 20:00:27 【问题描述】:当我调用findViewById()
访问按钮时,我得到了NullPointerException
。我想我明白为什么我会收到这个错误,但是我脑子里有一些问题没有解决。
好吧,我想我收到了这个错误,因为我将 findViewById()
调用从 onCreate()
方法内部移到了所有方法之外的类范围内。
所以现在我在onCreate()
方法之外初始化我的Button
和EditText
。
好吧,如果我理解正确,这是发生的(Null 错误),因为在 findViewById()
方法之后调用了 setContentView()
方法,所以这就是它抛出异常的原因。
但是我不明白的是,我在第二个活动中做了同样的事情,并且运行良好,没有任何空异常。我正在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();
);
【问题讨论】:
在字段初始化程序中调用findViewById()
总是会崩溃。您要么在查看错误的代码,要么在运行陈旧的构建,或者其他什么。所有给出的答案都是错误的。它与您稍后设置侦听器或以其他方式访问这些字段无关。第一个findViewById()
调用将立即抛出,早于onCreate()
运行。
【参考方案1】:
您不能使用此初始化:
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);
//...
在第二个活动中,您正在做一些不同的事情:
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
Button backButton = findViewById(R.id.su_backButton);
//...
这是正确的,因为您在 setContentView
调用之后使用 findViewById
内部的 findViewById
方法声明和初始化了 backButton
。
在第一个活动中,您使用signUpButton.setOnClickListener
设置侦听器,但signUpButton
未初始化(因为它在onCreate
方法之外)
同样在第二个活动中,其他被错误初始化的按钮在OnCreate
方法中没有使用。
【讨论】:
好吧,我也是这么想的。但是为什么我的第二个 Activity 没有导致任何异常? 两者都做同样的初始化... @Panagiss 因为在第二个活动中你使用了不同的东西:Button backButton = findViewById(R.id.su_backButton);
而不是signUpButton.setOnClickListener(new View.OnClickListener()
这里有什么区别?我不明白。请原谅我,但我看到我再次打电话给findViewById()
。但我只是想访问另一个View
@Panagiss 我已经更新了答案。在第一个活动中,您使用signUpButton.setOnClickListener
设置侦听器,但signUpButton
未初始化。在第二个活动中,您在设置侦听器之前正确使用了findViewById
。 OnCreate
方法中没有使用其他按钮。【参考方案2】:
在第二个activity中,你没有使用初始化错误的按钮,一旦你使用它们也会导致异常。
您使用了正确初始化的backButton。
【讨论】:
【参考方案3】:答案很简单。全局变量在调用 setContentView() 之前被初始化,这意味着 findViewById() 将返回 null。 findViewById() 如果找到则返回视图或为空。因为你还没有调用 setContentView,所以它找不到你想要的视图。
FirstActivity 和 SecondActivity 中的全局变量都为空。 FirstActivity 和 SecondActivity 的区别在于,您不能访问 SecondActivity 中的任何全局变量。
您在SecondActivity中使用的唯一视图是backButton,是您调用setContentView后获取的,所以当然不会抛出NullPointerException。
始终将变量声明为全局变量并在 onCreate() 中对其进行初始化。更好的是,尽量避免使用全局变量并通过方法参数传递它们。
【讨论】:
以上是关于在 setContentView() 之前调用 findViewById() 会导致 NullPointerException 但并非总是如此? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
(BEGINNER) 调用 setContentView 时出错?
Android 何时在 Activity.onCreate() 中的 setContentView() 之后首次调用 View.onMeasure()?