2016-08-03 21 views
1

Ich fange mit Android an und bin einfach verrückt nach den Werkzeugen mehrerer Fragmente. Ich habe zwei Fragmente in meiner MainActivity: QuestionDetail und QuestionListFragment. Wenn ich eine Fragment-Transaktion zum Ersetzen des QuestionDetail-Fragments verwende, wenn jemand in eine der QuestionListFragment-Optionen klickt, erhalte ich einen NullPointerException-Fehler.NullPointerException mit Fragment-Transaktionen

Ich habe versucht, dieses Problem seit Stunden zu beheben. Jede Hilfe wird sehr geschätzt.

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) 
+0

Bitte senden Sie sich ein stacktrace – Bostone

+0

Sorry, ich habe es –

+1

Sie den Blick auf das Fragment zugreifen, bevor es erstellt wird. Das kannst du nicht tun. anstelle von 'f1.showDetails (q.getName());', setzen Sie diesen Namen in die Fragmentargumente und verwenden Sie das Argument in der 'onCreateView', um die Ansichten zu füllen. – njzk2

Antwort

0

Erstens, verwenden Sie nicht getView() in onStart() - Sie sollten keine Aussicht auf an diesem Punkt zu erhalten. Zweitens sollten Sie keine Methoden direkt von außerhalb auf die Fragment-Instanzen aufrufen, in Ihrem Fall f1.showDetails(q.getName());. Dort hat das Fragment wieder keine Sicht. Wie Sie Argumente in Fragment übergeben, bevor Sie es in den FragmentManager laden, finden Sie unter Best practice for instantiating a new Android Fragment.


Nächster Punkt - sollten Sie Ihre Ansichten mit findViewById innerhalb von onCreateView initialisieren wie Sie für die andere Fragment Klasse tun. Zum Beispiel

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()); 
} 
+0

Vielen Dank für Ihre Hilfe. Es funktioniert jetzt. –

0

in QuestionListFragment:

gesetzt Wir Zuhörer recView für klicken, nicht Adapter. Sie sollten adapter.setOnClickListener mit

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 ersetzen:

QuestionID nicht initialisiert wurde, aber Sie haben es in dieser Zeile verwenden:

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

Basierend auf stacktrace und Ihren Code (nicht sicher, welches ist Zeile # 50 in Ihrem QuestionDetail) Äther txtName oder txtKind ergibt null (vielleicht beide), also aus welchen Gründen auch immer getView().findViewById(R.id.textQuestion) gibt null zurück. Wahrscheinlich, weil getView() in diesem Anruf nicht Sie erhalten eine übergeordnete Ansicht der Textview in Frage

Verwandte Themen