Abhishek Prakash
Abhishek Prakash

Reputation: 1

Why am I getting null pointer execepiton while finding a view of a fragment by ID?

I am getting error

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dhruv.parqueue/com.example.dhruv.parqueue.UserProfile}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.app.Dialog.findViewById(int)' on a null object reference

Here is my code

public class UserProfile extends AppCompatActivity {

    FragmentManager fm;
    CheckBox showPassword;
    Dialog passwordChangeDialog;
    private ImageView imageView;
    SharedPreferences preferences;
    private final int SELECT_PHOTO = 1;
    TextView nameText, contactText, emailText;
    PasswordChangeFragment passwordChangeFragment;
    Button confirmButton, changePassword, pickImage;
    EditText nameEdit, contactEdit, newPassword, oldPassword;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_profile);

        preferences = getSharedPreferences("MyFiles", MODE_PRIVATE);
        imageView = (ImageView) findViewById(R.id.imageView);
        pickImage = (Button) findViewById(R.id.btn_pick);
        changePassword = (Button) findViewById(R.id.changePassword);

        fm = getSupportFragmentManager();
        passwordChangeFragment = PasswordChangeFragment.newInstance("Change Password");
        passwordChangeDialog = passwordChangeFragment.getDialog();

        showPassword = (CheckBox) passwordChangeDialog.findViewById(R.id.show_password);
        newPassword = (EditText) passwordChangeDialog.findViewById(R.id.new_password);
        oldPassword = (EditText) passwordChangeDialog.findViewById(R.id.old_password);
        confirmButton = (Button) passwordChangeDialog.findViewById(R.id.confirm_btn);

        SharedPreferences.Editor editor = preferences.edit();
        editor.putBoolean("editButtonClicked", false);
        editor.commit();

        setProfile();

        pickImage.setVisibility(pickImage.GONE);
        changePassword.setVisibility(changePassword.GONE);

        new ProfileSyncTask().execute();

        pickImage.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View view) {
                Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
                photoPickerIntent.setType("image/*");
                startActivityForResult(photoPickerIntent, SELECT_PHOTO);
            }
        });

        changePassword.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                passwordChangeFragment.show(fm, "change_password_fragment");
            }
        });

        showPassword.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (!isChecked) {
                    newPassword.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
                } else {
                    newPassword.setInputType(129);
                }
            }
        });

        confirmButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (matchpassword(oldPassword.getText().toString())) {
                    String changedPassword = newPassword.getText().toString();
                    //Write this password to Database and Display Success using AlertFragment
                } else {
                    //Display Wrong Password using AlertFragment
                }
            }
        });

    }
.
.
.
}

I am getting the error at line:

showPassword = (CheckBox) passwordChangeDialog.findViewById(R.id.show_password);

Here is the full error

02-03 13:54:49.112 24058-24058/com.example.dhruv.parqueue E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dhruv.parqueue, PID: 24058
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dhruv.parqueue/com.example.dhruv.parqueue.UserProfile}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.app.Dialog.findViewById(int)' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2450)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2520)
    at android.app.ActivityThread.-wrap11(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1363)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5466)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.app.Dialog.findViewById(int)' on a null object reference
    at com.example.dhruv.parqueue.UserProfile.onCreate(UserProfile.java:97)
    at android.app.Activity.performCreate(Activity.java:6251)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2403)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2520) 
    at android.app.ActivityThread.-wrap11(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1363) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5466) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Here is the code for file change_password_fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="50dp">

    <EditText
        android:id="@+id/old_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/current_password"
        android:inputType="textPassword" />

    <EditText
        android:id="@+id/new_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/new_password"
        android:inputType="textVisiblePassword" />

    <CheckBox
        android:id="@+id/show_password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="@string/show_password" />

    <Button
        android:id="@+id/confirm_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:text="@string/Confirm" />

</LinearLayout>

Edit:

I changed my code (as per the suggestion) and implemented onCreateDialog as follows

public class PasswordChangeFragment extends DialogFragment {

    public PasswordChangeFragment() {
      }

    public static PasswordChangeFragment newInstance(String title, String userID) {
        PasswordChangeFragment frag = new PasswordChangeFragment();
        Bundle args = new Bundle();
        args.putString("title", title);
        args.putString("userID", userID);
        frag.setArguments(args);
        return frag;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.change_password_fragment, container);
    }

    View myView;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState){
        String title = getArguments().getString("title", "Change Password");
        final String userID = getArguments().getString("userID", "");
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage("foo")
                .setPositiveButton("Start timer", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        // Cancel
                    }
                });
        LayoutInflater inflater = getActivity().getLayoutInflater();
        myView = inflater.inflate(R.layout.change_password_fragment, null);
        builder.setView(myView);

        final CheckBox showPassword = (CheckBox) myView.findViewById(R.id.show_password);
        final EditText newPassword = (EditText) myView.findViewById(R.id.new_password);
        final EditText oldPassword = (EditText) myView.findViewById(R.id.old_password);
        final Button confirmButton = (Button) myView.findViewById(R.id.confirm_btn);

        showPassword.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (!isChecked) {
                    newPassword.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
                } else {
                    newPassword.setInputType(129);
                }
            }
        });

        confirmButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Helper helper = new Helper();
                try {
                    if (helper.matchPassword(userID, oldPassword.getText().toString())) {
                        String changedPassword = newPassword.getText().toString();
                        //Write this password to Database and Display Success using AlertFragment
                    } else {
                        //Display Wrong Password using AlertFragment
                    }
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        return builder.create();
    }

    @Override
    @Nullable
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // Get field from view
        String title = getArguments().getString("title", "Change Password");
        final String userID = getArguments().getString("userID", "");
        // Fetch arguments from bundle and set title
        FragmentManager fm = getActivity().getSupportFragmentManager();
        PasswordChangeFragment passwordChangeFragment = PasswordChangeFragment.newInstance(title, userID);
    }
}

Now I am getting the error

FATAL EXCEPTION: main
      Process: com.example.dhruv.parqueue, PID: 3564
      android.util.AndroidRuntimeException: requestFeature() must be called before adding content
      at com.android.internal.policy.PhoneWindow.requestFeature(PhoneWindow.java:317)
      at com.android.internal.app.AlertController.installContent(AlertController.java:231)
      at android.app.AlertDialog.onCreate(AlertDialog.java:423)
      at android.app.Dialog.dispatchOnCreate(Dialog.java:394)
      at android.app.Dialog.show(Dialog.java:295)
      at android.support.v4.app.DialogFragment.onStart(DialogFragment.java:406)
      at android.support.v4.app.Fragment.performStart(Fragment.java:1986)
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1102)
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
      at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
      at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
      at android.os.Handler.handleCallback(Handler.java:739)
      at android.os.Handler.dispatchMessage(Handler.java:95)
      at android.os.Looper.loop(Looper.java:148)
      at android.app.ActivityThread.main(ActivityThread.java:5417)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Upvotes: 0

Views: 878

Answers (3)

Silambarasan Poonguti
Silambarasan Poonguti

Reputation: 9442

try this...

 PasswordChangeFragment passwordChangeFragment  = new PasswordChangeFragment().newInstance("Change Password");
 Dialog passwordChangeDialog = passwordChangeFragment.getDialog();

Upvotes: 0

Rey Pham
Rey Pham

Reputation: 605

passwordChangeFragment = PasswordChangeFragment.newInstance("Change Password");
passwordChangeDialog = passwordChangeFragment.getDialog();

Calling getDialog() method right after creating your DialogFragment will return null because it isn't created yet. DialogFragment will call onCreateDialog() later to get the dialog, so you should override this method and put your findViewById() methods there.

Upvotes: 1

Blackbelt
Blackbelt

Reputation: 157437

The PasswordChangeFragment, live every Fragment, has to go through its lifecycle. You can't make any assumption on when Android is going to call onCreatDialog whose result is returned by getDialog(). You should get rid of

 showPassword = (CheckBox) passwordChangeDialog.findViewById(R.id.show_password);
 newPassword = (EditText) passwordChangeDialog.findViewById(R.id.new_password);
 oldPassword = (EditText) passwordChangeDialog.findViewById(R.id.old_password);
 confirmButton = (Button) passwordChangeDialog.findViewById(R.id.confirm_btn);

From your Activity and deal with them in the DialogFragment's subclass. There are a lot of different ways to pass the results back to your Activity if you need them

Upvotes: 1

Related Questions