Search code examples
androidnullpointerexceptionfindviewbyidsetcontentview

Calling findViewById() before setContentView() causes NullPointerException but not always?


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

Solution

  • 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.