1

I've got an AppCompatActivity which is the main View of the app. There I've got an OptionsMenu with a button to display a drawer menu and another button to filter the results (Because each MenuItem in the drawer are different Listfragments).

What I need to accomplish is, when clicking the filter button on the OptionsMenu, open a fragment with all the filtering criteria.

So this is the code managing the explained above:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_menu:

            if (drawer.isDrawerOpen(GravityCompat.START)) {
                hideDrawer();
            } else {
                showDrawer();
            }

            return true;
        case R.id.action_filter:

            fragmentManager = getFragmentManager();

            fragment = new FilterFragment();
            args.putInt("idList", idList);
            fragment.setArguments(args);

            fragmentManager.beginTransaction().replace(R.id.drawer_layout, fragment).commit();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Doing that the Fragment shows up and then I get a NPE:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TableRow.setVisibility(int)' on a null object reference

Fragment onCreateViewMethod

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

    setHasOptionsMenu(true);
    getActivity().invalidateOptionsMenu();
    skbrDays = getActivity().findViewById(R.id.seekBar);
    daysLostRow = getActivity().findViewById(R.id.daysLostRow);
    genderRow = getActivity().findViewById(R.id.genderRow);
    locationRow = getActivity().findViewById(R.id.locationRow);
    rgupGender = getActivity().findViewById(R.id.rgupGender);
    rgupType = getActivity().findViewById(R.id.rgupType);
    btnBreed = getActivity().findViewById(R.id.btnBreed);
    recyclerView = getActivity().findViewById(R.id.recyclerView);

    daysLostRow.setVisibility(View.VISIBLE);

    return inflater.inflate(R.layout.activity_filter, container, false);
}

Ok, so I'm getting the NPE because getActivity() is returning null. And now I have to guess, not really knowing the reason, that is beacuse I'm not replacing the fragment on onCreate method from the activity?

If that is the reason how can I achieve the same result calling the fragment from onCreate?

Paula Daniela
  • 115
  • 2
  • 10
  • It's not `getActivity()`. It's `findViewById(R.id.daysLostRow)`. You may want to throw that fragment code away and start again: fragments should not generally depend on the kind of activity that uses them. – M. Prokhorov Feb 14 '18 at 14:13
  • @M.Prokhorov but findViewById() is not an inherited method by Fragment – Paula Daniela Feb 14 '18 at 14:33
  • yes, but your exception doesn't say "*attempted to invoke findViewById on a null object reference*" either, which means `getActivity()` returns something. However, `setVisibility` is only called once in code you're showing, which means `daysLostRow` is `null`. And where did that variable came from, you think? – M. Prokhorov Feb 14 '18 at 14:39
  • @M.Prokhorov you are right getActivity() isn't returning null. daysLostRow is a global variable previously defined. But the problem isn't with that particular variable, any method I call on any of the other Views give me a NPE. – Paula Daniela Feb 14 '18 at 14:46
  • That would be because it is `null`. Most likely because original activity doesn't have any elements with `R.id.daysLostRow` in its view. – M. Prokhorov Feb 14 '18 at 14:48
  • Mm... No, the original activity doesn't have it. It is defined inside the Fragment class. – Paula Daniela Feb 14 '18 at 14:52
  • Then there you have it. You are trying to get something which activity doesn't have, so it returns you `null` instead. To do what you want, you will need to first create (inflate) the view from its `layout-id`, and then search *that* for a view with id. – M. Prokhorov Feb 14 '18 at 14:55
  • Ok thank you, I think I understand now. Isn't that what Hiral Pancholi proposed? – Paula Daniela Feb 14 '18 at 14:59
  • It is. It is also a duplicate of the other question I linked. Hiral's answer is also not a good one, because it doesn't explain anything, she just "writes the code instead of you". – M. Prokhorov Feb 14 '18 at 15:00
  • Yeah, I know is not a good answer. But It solved the problem, I would have liked that she explained why it worked. If you would've posted the solution as an answer I had chosen yours. – Paula Daniela Feb 14 '18 at 15:03
  • I don't think I need to. There is already a highly viewed question and an answer to it out there. This question's title is misleading as well, so it's unlikely to help future readers who would look for something related to `onOptionsItemSelected`, because this question actually isn't related to that. – M. Prokhorov Feb 14 '18 at 15:05

1 Answers1

2

Replace your code in onCreateView to below code.

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
 View rootView = inflater.inflate(R.layout.activity_filter, container, false);
    setHasOptionsMenu(true);
    getActivity().invalidateOptionsMenu();
    skbrDays = rootView.findViewById(R.id.seekBar);
    daysLostRow = rootView.findViewById(R.id.daysLostRow);
    genderRow = rootView.findViewById(R.id.genderRow);
    locationRow = rootView.findViewById(R.id.locationRow);
    rgupGender = rootView.findViewById(R.id.rgupGender);
    rgupType = rootView.findViewById(R.id.rgupType);
    btnBreed = rootView.findViewById(R.id.btnBreed);
    recyclerView = rootView.findViewById(R.id.recyclerView);

    daysLostRow.setVisibility(View.VISIBLE);

    return rootView;
}
Paula Daniela
  • 115
  • 2
  • 10