1

Well i get a NullPointerException when i I call findViewById() to access a Button. I think I understand why I'm getting this error but there are some questions I have unsolved in my head. Well I think I'm getting this error because I moved the findViewById() calls from inside the onCreate() method to class scope, outside of all the methods.

So now I'm initializing my Button's and EditText's outside the onCreate() method. Well if I understand correctly, this is happening(Null error) cause the setContentView() method is called after the findViewById() method, so that's why it throws an Exception.

But what I don't understand is that I have done the same thing in my second activity and works well without any null exception. And I'm initializing my Buttons etc outside the onCreate() method!

It does confuse me a little bit. Any help clearing this in my head would be much appreciated.

First 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();
                }
        });

}

Second 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();
            }
        }); 
Panagiss
  • 3,154
  • 2
  • 20
  • 34
  • Calling `findViewById()` in a field initializer will always crash. You're either looking at the wrong code, or running a stale build, or something. All the of the given answers are wrong. It has nothing to do with when you set a listener, or otherwise access, those fields later on. The first `findViewById()` call will throw immediately, long before `onCreate()` runs. – Mike M. Sep 10 '20 at 11:05

3 Answers3

-1

You can't use this initialization:

public class SecondActivity extends AppCompatActivity {

    private Button signUpButton= findViewById(R.id.lo_signUpButton);
    //....
}

Use:

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);
        //...
    }
}

In the 2nd Activity you are doing something different:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_signup);
    Button backButton = findViewById(R.id.su_backButton);
    //...
}

and it is correct since you declaring and initializing the backButton with the findViewById method inside the onCreate after the setContentView call.

In the 1st Activity you are setting the listener with signUpButton.setOnClickListener but the signUpButton is not initialized (since it is outside the onCreate method)

Also in the 2nd Activity the other buttons that are wrongly initialized are not used in the OnCreate method.

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • OK that's what i also think. But why my second Activity doesn't cause any Exception? – Panagiss Sep 10 '20 at 10:41
  • Both do the same initialization... – Panagiss Sep 10 '20 at 10:42
  • 1
    @Panagiss Because in the 2nd Activity you are using something different: `Button backButton = findViewById(R.id.su_backButton);` instead of `signUpButton.setOnClickListener(new View.OnClickListener()` – Gabriele Mariotti Sep 10 '20 at 10:43
  • What's the difference here? I don't get it. Forgive me but i see that im calling ```findViewById()``` again. But i just trying to access another ```View``` – Panagiss Sep 10 '20 at 10:46
  • Yeah ok just for one ```Button```. What about the other ones? – Panagiss Sep 10 '20 at 10:47
  • Is it because i add listener to that ```Button``` right? I think i see what you are saying – Panagiss Sep 10 '20 at 10:48
  • 1
    @Panagiss I've updated the answer. In the 1st Activity you are setting the listener with `signUpButton.setOnClickListener` but the `signUpButton` is not initialized. In the 2nd Activity instead you are using the `findViewById` correctly before setting the listener. The other button are not used in the `OnCreate` method. – Gabriele Mariotti Sep 10 '20 at 10:50
-1

In second activity, you have not used the buttons that are wrongly initialized, once you use them, it will cause exception too.

You have used backButton which is correctly initialized.

Bilal Aslam
  • 769
  • 6
  • 13
-2

The answer is quite simple. the global variables get initialized before setContentView() is called, meaning what findViewById() will return null. findViewById() returns the view if found or null. As you didn't call setContentView yet, it cannot find the view you want.

The global variables in FirstActivity as well as SecondActivity are all null. The difference between FirstActivity and SecondActivity is, that you don't access any global variable in SecondActivity.

The only view you used in SecondActivity is backButton, which you retrieved after calling setContentView, so of course, no NullPointerException will be thrown.

Always declare the variable as globally and initialize it in onCreate(). Even better, try to avoid global variables and pass them though method parameters.

Yochyo
  • 72
  • 3
  • 5