Background & Problem:
I have a custom Fragment
class. I reuse this fragment class for multiple status displays. In the parent Activity
, I load the fragment and call a method on the fragment to set some text, etc. When I do this, I hit a NullPointerException
. The reason is onCreateView() has not yet been called, i.e. the view doesn't exist, thus accessing a TextView
to call .setText(String)
will ofcourse run into a NullPointerException
.
Fragment Class
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.example.app.R;
public class CopyStaticFragment extends Fragment {
private String initialActionText, initialSecondaryText, initialTitleText;
private TextView textViewTitle, textViewSecondary;
private Button btnAction;
private View.OnClickListener actionCallback;
public void setActionButtonListener(View.OnClickListener actionCallback) {
this.actionCallback = actionCallback;
}
public CopyStaticFragment() {
}
public CopyStaticFragment(View.OnClickListener actionCallback) {
this.actionCallback = actionCallback;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_main_status, container, false);
textViewTitle = layout.findViewById(R.id.textViewTitle);
textViewTitle.setText(initialTitleText);
textViewSecondary = layout.findViewById(R.id.textViewSecondary);
textViewSecondary.setText(initialSecondaryText);
btnAction = layout.findViewById(R.id.btnAction);
btnAction.setText(initialActionText);
btnAction.setOnClickListener(v -> {
if(actionCallback != null) {
actionCallback.onClick(v);
}
});
return layout;
}
public void setPrimaryText(String text) {
textViewTitle.setText(text);
}
public void setSecondaryText(String text) {
textViewSecondary.setText(text);
}
public void setActionText(String text) {
btnAction.setText(text);
}
public void setInitialActionText(String text) {
this.initialActionText = text;
}
public void setInitialSecondaryText(String text) {
this.initialSecondaryText = text;
}
public void setInitialTitleText(String text) {
this.initialTitleText = text;
}
}
Somewhere in my main activity, as a callback response from a Service
status, I will do something like:
if (instance.getUnbackedUpCount() > 0) {
// Load first fragment - i.e. we can backup content
getSupportFragmentManager().beginTransaction()
.replace(R.id.frameCurrentStatus, copyStartFragment)
.commit();
capacityControlFragment.setInfoIconVisible(true);
} else {
getSupportFragmentManager().beginTransaction()
.replace(R.id.frameCurrentStatus, copyFinishFragment)
.commit();
}
where copyStartFragment
& copyFinishFragment
are instances of the above mentioned fragment.
Note:
Depending on the Service
status update interval, the call to replace()
fragments can be almost instantaneous - which I figure is the actual problem.
My workaround:
Is to have initial setters for all views and their properties. e.g. initialTitleText
, initialMessageText
, initialActionButtonText
, initialActionButtonVisibility
, etc. I feel this is hack'ish and not inline with the intended design philisophy of Fragment use.
My Question
Is this a design problem on my part for encountering such an error or is there a workaround to call the onCreateView()
sooner?