Calling findViewById() from DialogFragment subclass gives NullPointerException

2.3k views Asked by At

In below code, I try to display a basic dialog upon button click. The dialog shows some needs to show some text. I have got it working after i stumpled upon an error, but i still got a question to why that error occurs. In DialogFragmentSubclass.onCreateView() i get a reference to a TextView by calling findViewById(R.id.someIdValue). This gives me NullPointerException. However, getting the reference by calling:

View v = inflate.inflate(someREsourceValue, container, fals);
TextView tv = (TextView) v.findViewById(R.id.someValue);

seems to do the trick. Why does this work, and the other gives me a NullPointerException? (See below for full code)

public class MainActivity extends Activity {
    DownloadImageDialogFragment myDialog;   

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

        // get reference to buttons
        Button buttonDownloadImage = (Button) findViewById(R.id.downloadImage);
        buttonDownloadImage.setText("Download new Image");

        // upon button click, show a Dialog
        buttonDownloadImage.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                FragmentTransaction ft = getFragmentManager().beginTransaction();

                myDialog = new DownloadImageDialogFragment();
                myDialog.show(ft, null);            
            }
        });

    }

    private class DownloadImageDialogFragment extends DialogFragment {              
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {

                View v = inflater.inflate(R.layout.fragment_dialog, container, false);
                // TextView tv = findViewById(R.id.dialogTextView); // this gives an error
                TextView tv = (TextView) v.findViewById(R.id.dialogTextView); // this works
                tv.setText("This is my dialog");
                return v;
            }
        }
}

And here, the layout file for the dialog:

    <TextView 
        android:id="@+id/dialogTextView"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content" />

</LinearLayout>
2

There are 2 answers

1
Larry Schiefer On BEST ANSWER

When you are calling findViewById(), you are doing so from an inner class of your Activity, which is where this method comes from. Since that view id doesn't exist in your activity's layout, you get null. Your dialog fragment has to inflate its layout (as you have found) before it can get the views defined within it.

1
SeahawksRdaBest On

To explain this you really need to understand what a view is.

According to the Android website a view,

occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.). The ViewGroup subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.

In essence it is a class. It extends Object (java base class) and implements Drawable.Callback KeyEvent.Callback AccessibilityEventSource. If you are newish to JAVA read this to understand implements vs extends.

Now if you read about the findViewById(...) function you will see the function returns a View object. This is NOT a Textview Object. So there only you should know you need to do some additional step to make the code base work.

Now if you delve deeper and read the TextView Android page you will see it extends the View class. So it inherits everything from that class. This is basically why you need to pass a "type" to the View which was returned by the findViewById(int id) function.

Finally it is all about where you are calling your functions from. If you call your function from a Activity layout which doesn't have the View defined you will get the NULL pointer exception like you did. I believe in this case you were calling the function from a sub activity which has its own xml and does not have the textview defined. Therefore you must inflate the view which has it. Adding the TextView tag does that.