Avoid Call Instance Method in Constructor to Prevent NullPointerException


Avoid Call Instance Method in Constructor

Calling am instance method while the object is being constructed is anti-pattern and error prone, can easily lead to bugs.

public class MyDialog extends Dialog {

  private final TextView bodyText;

  public MyDialog(Context context) {
    super(context);
    setContentView(R.layout.dialog);
    bodyText = findViewById(R.id.text);
  }

  public void setText( CharSequence text) {
    bodyText.setText(text);
  }

  public CharSequence getProgressBarText() {
    return bodyText.getText();
  }
}

Checker framework would report error like below:

error: [method.invocation.invalid] call to setContentView(int) not allowed on the given receiver.
    setContentView(R.layout.dialog);
                  ^
  found   : @UnderInitialization(android.app.Dialog.class) @NonNull Dialog
  required: @Initialized @NonNull Dialog
MyDialog.java error: [method.invocation.invalid] call to <T>findViewById(int) not allowed on the given receiver.
    bodyText = findViewById(R.idtext);
                           ^
  found   : @UnderInitialization(android.app.Dialog.class) @NonNull Dialog
  required: @Initialized @NonNull Dialog

This can be fixed:

public class MyDialog extends Dialog {

  public static MyDialog newInstance(Context context) {
    View dialogView = LayoutInflater.from(context).inflate(R.layout.dialog, null);
    MyDialog dialog = new MyDialog(context, dialogView);
    dialog.setUp(dialogView);
    return dialog;
  }

  private final TextView bodyText;

  private CarProgressDialog(Context context, View dialogView) {
    super(context);
    bodyText = Preconditions.checkNotNull(dialogView.findViewById(R.id.text));
  }

  public void setProgressBarText(CharSequence text) {
    bodyText.setText(text);
  }

  public CharSequence getProgressBarText() {
    return bodyText.getText();
  }
}

Another approach:

public class MyDialog extends Dialog {

  private CharSequence text;
  @MonotonicNonNull private TextView bodyText;

  public MyDialog(Context context) {
    super(context);
    this.text = "";
  }
  public MyDialog(Context context, CharSequence text) {
    super(context);
    this.text = text;
  }

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

    bodyText = findViewById(R.id.text);
    bodyText.setText(text);
  }

  public void setText(CharSequence text) {
    this.text = text;
    if (bodyText != null) {
      bodyText.setText(text);
    }
  }

  public CharSequence getText() {
    return text;
  }
}

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)