0

When I try to setText() on an EditText I keep getting this error, I can't see where I'm going wrong. I'd like to understand the logic behind this error. I'm sure it's something small but it's really bugging me now.

01-25 10:20:44.267 14325-14325/com.example.gregsquibbs.greg_squibbs_todoapp3 E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.gregsquibbs.greg_squibbs_todoapp3, PID: 14325 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.gregsquibbs.greg_squibbs_todoapp3/com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) at android.app.ActivityThread.-wrap11(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference at com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoFragment.setMessage(EditTodoFragment.java:56) at com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoActivity.onCreate(EditTodoActivity.java:41) at android.app.Activity.performCreate(Activity.java:6975) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)  at android.app.ActivityThread.-wrap11(Unknown Source:0)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)  at android.os.Handler.dispatchMessage(Handler.java:105)  at android.os.Looper.loop(Looper.java:164)  at android.app.ActivityThread.main(ActivityThread.java:6541)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

This is where I create the etMessage and use setText()

public class EditTodoFragment extends Fragment implements EditTodoContract.View {

private EditTodoContract.Presenter presenter;
private EditText etMessage;


public EditTodoFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.edit_todo_fragment, container, false);

    System.out.println("Step 2 - Fragment check");
    etMessage = (EditText) view.findViewById(R.id.etMessage);


    return view;
}

public void setPresenter(EditTodoContract.Presenter todoPresenter) {
    this.presenter = todoPresenter;
}

public String getMessage() {
    String message = etMessage.getText().toString();
    return message;
}

public void setMessage(String message) {
    etMessage.setText(message);
}

}

Here is the XML file

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoActivity">


<EditText
    android:id="@+id/etMessage"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:layout_marginBottom="10dp"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginTop="10dp"
    android:background="@drawable/rect"
    android:ems="10"
    android:gravity="top"
    android:inputType="textShortMessage" />

<Button
    android:id="@+id/bSave"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Save"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    android:onClick="saveButtonClicked"
    android:layout_gravity="center_horizontal|bottom"


    />

Here is where setMessage() gets called in the activity

public class EditTodoActivity extends AppCompatActivity {
private String message;
private int position;
private EditTodoFragment editTodoFragment;
private EditTodoPresenter editTodoPresenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.edit_todo_activity);

    System.out.println("Step 1");

    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = fm.findFragmentById(R.id.contentFrameContainer);

    if (fragment == null){
        editTodoFragment = new EditTodoFragment();
        fm.beginTransaction()
                .add(R.id.contentFrameContainer, editTodoFragment)
                .commit();
        editTodoPresenter = new EditTodoPresenter(editTodoFragment);
    }


    message = getIntent().getStringExtra(IntentConstants.INTENT_MESSAGE_DATA);
    position = getIntent().getIntExtra(IntentConstants.INTENT_ITEM_POSITION, -1);
    editTodoFragment.setMessage(message);

}

public void saveButtonClicked(View v) {
    if(editTodoFragment.getMessage().equals("")) {
    } else {
        String changedMessage = (editTodoFragment.getMessage());
        Intent intent = new Intent();
        intent.putExtra(IntentConstants.INTENT_CHANGED_MESSAGE, changedMessage);
        intent.putExtra(IntentConstants.INTENT_ITEM_POSITION, position);
        finish();
    }
}

}


Edit: On this line in the fragment

        etMessage = (EditText) view.findViewById(R.id.messageField);

When I hover over the casting (EditText) it says

Casting 'view.findViewById(R.id.messageField)' to 'EditText' is redundant less... (⌘F1) This inspection reports unnecessary cast expressions.

I don't know whether that has anything to do with it or not.

Greg
  • 35
  • 4

4 Answers4

0

Probably the error is that you have defined etMessage in other file than edit_todo_fragment. That's why you are not getting a compilation error, since the reference to etMessage exists, but it does not exists in your inflated view so thus you got the NPE.

moictab
  • 959
  • 6
  • 27
0

There is no garrenty that editTodoFragment.setMessage(message); will be called after your EditText initialized by this line

etMessage = (EditText) view.findViewById(R.id.etMessage);

In your case your code is setting text to EditText before it's initialized.

Best practice is send data via Bundle to Fragment and set Text after EditText is initialized.

Check this answer

Sample Code:

In EditTodoActivity

 message = getIntent().getStringExtra(IntentConstants.INTENT_MESSAGE_DATA);
 if (fragment == null){
    editTodoFragment = new EditTodoFragment();
    // 
    Bundle bundle = new Bundle();
    bundle.putInt(key, message);
    fragment.setArguments(bundle);

    fm.beginTransaction()
            .add(R.id.contentFrameContainer, editTodoFragment)
            .commit();
    editTodoPresenter = new EditTodoPresenter(editTodoFragment);
 }

In EditTodoFragment onCreate

Bundle bundle = this.getArguments();
if (bundle != null) {
    message = bundle.getString(key, defaultValue);
}

In EditTodoFragment onCreateView

etMessage = (EditText) view.findViewById(R.id.etMessage);
etMessage.setText(message);
Abu Yousuf
  • 5,729
  • 3
  • 31
  • 50
0

As I understood from logs you're calling setMessage method from onCreate method of your activity. But the problem is Activity's onCreate is called earlier than Fragment's onCreateView, so your EditText is not initialized at that moment.

greenfrvr
  • 643
  • 6
  • 19
-1

first you have to define this EditText belong to witch view then, after you inflate your view you should do this.

    View view = inflater.inflate(R.layout.edit_todo_fragment, container, false);
    etMessage = view.findViewById(R.id.etMessage);
    etMessage.setText("your message...")

if you call set text before it, you see this error

or

this view (etMessage) is not in this layout (edit_todo_fragment)

Ashkan
  • 1,357
  • 4
  • 16
  • 37