0

У меня есть два фрагмента: ввод сверху и результат снизу.Почему getFragmentManager(). FindFragmentById возвращает null (вызывает NullPointerException)

Изначально отображается только InputFragment. Когда пользователь нажимает кнопку «Рассчитать», отображается «Результат». Все работает хорошо.

ResultFragment имеет кнопку «Очистить все», в которой я хочу очистить поля InputFragment и заставить ResultFragment уйти (скрыть, удалить или отсоединить, мне все равно, пока он станет невидимым) ,

Но он падает, когда вы нажимаете кнопку «Очистить все». В частности, в методе clearResult() происходит фатальный NullPointerException.

Здесь MainActivity.java

import android.support.v7.app.ActionBarActivity; 
import android.app.Fragment; 
import android.app.FragmentManager; 
import android.app.FragmentTransaction; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.MenuItem; 

public class MainActivity extends ActionBarActivity implements InputFragment.InputFragmentListener, ResultFragment.ResultFragmentListener { 

    private static FragmentManager manager; 

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

     if(savedInstanceState == null){ 
      Fragment inputFragment = new InputFragment(); 

      manager = getFragmentManager(); 
      FragmentTransaction transaction = manager.beginTransaction(); 
      transaction.add(R.id.fragment_container_top,inputFragment).commit(); 
     } 
    } 

    //This gets called by the Input Fragment when the user clicks the Calculate button 
    @Override 
    public void createResult(String resultPhrase) { 

     ResultFragment resultFragment = (ResultFragment) manager.findFragmentById(R.id.result_fragment); 

     if (resultFragment != null){ 
      /* if resultFragment is available, we can modify it's TextView 
      * by calling the method to do the updating 
      */ 
      //ResultFragment.theResultText.setText(resultPhrase); 
      resultFragment.setResultText(resultPhrase); 
     }else{ 
      /*...otherwise the fragment has to be created */ 
      ResultFragment newResultFragment = new ResultFragment(); 
      Bundle args = new Bundle(); 
      args.putString(ResultFragment.resultTxt, resultPhrase); 
      newResultFragment.setArguments(args); 

      FragmentTransaction transaction = manager.beginTransaction(); 
      transaction.replace(R.id.fragment_container_bottom, newResultFragment); 
      transaction.addToBackStack(null); 
      transaction.commit();  

      //((TextView) newResultFragment.getView().get).setText(resultPhrase); 

     } 


    } 


    //This gets called in the ResultFragment when the user clicks the Clear All button 
    @Override 
    public void clearResult() { 
     //InputFragment inp_frag = (InputFragment) getFragmentManager().findFragmentById(R.id.fragment_input); 


     // This damned object is null again 
     //inp_frag.clearFields(); 
     Fragment res_frag = getFragmentManager().findFragmentByTag("resultfragtag"); 

     FragmentTransaction transaction = getFragmentManager().beginTransaction(); 
     //res_frag.clearResult(); 
     transaction.hide(res_frag); 
     transaction.commit(); 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 
} 

Вот LogCat сообщение:

03-01 23: 30: 34,663: Е/AndroidRuntime (3399): неустранимые: основные
03-01 23: 30: 34.663: E/AndroidRuntime (3399): Процесс: com.example.amortizersandbox, PID: 3399
03-01 23: 30: 34.663: E/AndroidRuntime (3399): java.lang.NullPointerException : Попытка написать в поле 'int android.app.Fragment.mNextAnim' на нулевая ссылка на объект
03-01 23: 30: 34,663: E/AndroidRuntime (3399): в android.app.BackStackRecord.run (BackStackRecord.java:797)

ответ

1

Для замены/добавления использовать фрагмент:

getSupportFragmentManager() 
          .beginTransaction() 
          .setCustomAnimations(R.anim.slide_in_top, 
            R.anim.slide_out_top) 
          .add(R.id.list_frame, fr, "tag").commit(); 

Теперь для нахождения этого использовать фрагмент:

Fragment fr = getSupportFragmentManager() 
       .findFragmentByTag("tag"); 
     if (fr != null) { 
      //do your stuff 
     } else { 
//fr is null here 
     } 
+0

Это также хороший ответ. Ключевой момент, который я пропустил в своем коде: добавление имени тега в транзакции (я добавлял в xml фрагмента - это не сработало). Спасибо огромное! – D3VON

+0

Если мой ответ поможет вам, вы можете пометить его правильно. –

+0

Где кнопка "correct"? (Я видел этот комментарий 1000 раз раньше, но только недавно начал задавать вопросы и не знаю, как отметить его правильно. - Совершенно не очевидно). – D3VON

0

Вам не нужно использовать тег «resultfragtag "при добавлении InputFragment.

Попробуйте добавить его OnCreate:

transaction.add(R.id.fragment_container_top,inputFragment,"resultfragtag").commit(); 
+0

Спасибо всем! Все указали на использование тега вместо id. Я не знал, чтобы добавить тег в транзакцию - я положил его в xml фрагмента. Так что этот маленький намек действительно справился с этой задачей. (за исключением того, что он имеет смешанный вход и результат, но это легко увидеть и исправить, если кто-либо использует этот пример). – D3VON

0

Использование:

Fragment res_frag = getFragmentManager().findFragmentById(R.id.result_fragment); 

заменить:

Fragment res_frag = getFragmentManager().findFragmentByTag("resultfragtag"); 
Смежные вопросы