1

I'm starting with android and just getting crazy with the implements of multiple fragments. I have two fragments in my MainActivity: QuestionDetail and QuestionListFragment. When I use a fragment transactions to replace the QuestionDetail fragment when someone click in one of the QuestionListFragment options I get a NullPointerException error.

I have been trying to fix this issue for hours. Any help is greatly appreciated.

QuestionDetail

public class QuestionListFragment extends Fragment{

private RecyclerView recView;
public static QuestionAdapter adapter;
private QuestionListener listener;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_question_list, container, false);
    recView = (RecyclerView) v.findViewById(R.id.recView);
    return v;
}

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

    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    recView.setLayoutManager(layoutManager);

    adapter = new QuestionAdapter(QuestionCatalog.getQuestionCatalog().getQuestionList().getList());
    adapter.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            if (listener!=null) {
                listener.onQuestionListener(adapter.getItem(recView.getChildAdapterPosition(v)));
            }
        }
    });
    recView.setAdapter(adapter);
}

public interface QuestionListener {
    void onQuestionListener(Question q);
}

public void setQuestionListener(QuestionListener listener) {
    this.listener=listener;
}

QuestionDetail

public class QuestionDetail extends Fragment {
// We use an ID to know which Question we're using
private long questionId;

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


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_question_detail, container, false);
}

@Override
public void onStart() {
    super.onStart();
    //Fragments don’t include findViewById(). To get a reference to a view, we use getView()
    View view = getView();
    if (view != null) {
        TextView title = (TextView) view.findViewById(R.id.textQuestion);
        Question question = QuestionCatalog.getQuestionCatalog().getQuestionList().getList().get((int) questionId);
        title.setText(question.getName());
        TextView kind = (TextView) view.findViewById(R.id.textKind);
        kind.setText(question.getKind());
    }
}

public void showDetails(String texto) {
    TextView txtName = (TextView)getView().findViewById(R.id.textQuestion);
    TextView txtKind = (TextView)getView().findViewById(R.id.textKind);
    txtName.setText(texto);
    txtKind.setText(texto);
    }
}

MainActivity

public class MainActivity extends AppCompatActivity implements QuestionListFragment.QuestionListener {

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

    QuestionListFragment frg =(QuestionListFragment)getFragmentManager().findFragmentById(R.id.listFragment);
    frg.setQuestionListener(this);
}

@Override
public void onQuestionListener(Question q) {
    Toast.makeText(this, "num: " + q.getName(),
            Toast.LENGTH_LONG).show();
    FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    QuestionDetail f1 = new QuestionDetail();
    f1.showDetails(q.getName());
    t.replace(R.id.detailFragment,f1);
    t.addToBackStack(null);
    t.commit();
}

stacktrace

08-04 09:54:11.914 22277-22277/com.hfad.predictandwin E/AndroidRuntime: FATAL EXCEPTION: main
                                                                    java.lang.NullPointerException
                                                                        at com.hfad.predictandwin.Fragments.QuestionDetail.showDetails(QuestionDetail.java:50)
                                                                        at com.hfad.predictandwin.MainActivity.onQuestionListener(MainActivity.java:34)
                                                                        at com.hfad.predictandwin.Fragments.QuestionListFragment$1.onClick(QuestionListFragment.java:55)
                                                                        at com.hfad.predictandwin.QuestionAdapter.onClick(QuestionAdapter.java:61)
                                                                        at android.view.View.performClick(View.java:4475)
                                                                        at android.view.View$PerformClick.run(View.java:18786)
                                                                        at android.os.Handler.handleCallback(Handler.java:730)
                                                                        at android.os.Handler.dispatchMessage(Handler.java:92)
                                                                        at android.os.Looper.loop(Looper.java:176)
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5419)
                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                        at java.lang.reflect.Method.invoke(Method.java:525)
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
                                                                        at dalvik.system.NativeStart.main(Native Method)

3 Answers3

0

in QuestionListFragment:

We set click listener for recView, not adapter. You should replace adapter.setOnClickListener with

recView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recView, new ClickListener() {
            @Override
            public void onClick(View view, int position) {
                // do something with position.
            }

            @Override
            public void onLongClick(View view, int position) {

            }
        }));

in QuestionDetail:

questionId wasn't initialized but you have use it in this line:

Question question = QuestionCatalog.getQuestionCatalog().getQuestionList().getList().get((int) questionId);
xxx
  • 3,315
  • 5
  • 21
  • 40
0

Based on stacktrace and your code (not sure which one is line #50 in your QuestionDetail) ether txtName or txtKind evaluates to null (maybe both), so for whatever reason getView().findViewById(R.id.textQuestion) returns null. Probably because getView() in that call doesn't get you a parent view of the TextView in question

Bostone
  • 36,858
  • 39
  • 167
  • 227
0

First, don't use getView() in onStart() - You shouldn't have a view to get at that point. Second, you shouldn't be calling methods directly on the Fragment instances from elsewhere, in your case f1.showDetails(q.getName());. There, again, the Fragment has no View. Please see Best practice for instantiating a new Android Fragment for how to pass arguments into Fragment before you load it into the FragmentManager.


Next point - you should initialize your views using findViewById inside of onCreateView just like you did for the other Fragment class. For example,

private TextView txtName, txtKind;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_question_detail, container, false);

    txtName = (TextView) rootView.findViewById(R.id.textQuestion);
    txtKind = (TextView) rootView.findViewById(R.id.textKind);

    // TODO: Read the link how to use these
    Bundle arguments = getArguments();

    Question question = QuestionCatalog.getQuestionCatalog()
                .getQuestionList().getList().get((int) questionId);
    showQuestion(question);

    return view;
}

private void showQuestion(Question q) {
    txtName.setText(q.getName());
    txtKind.setText(q.getKind());
}
Community
  • 1
  • 1
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245