0

我有兩個片段:輸入在頂部,結果在底部。爲什麼getFragmentManager()。findFragmentById返回null(導致NullPointerException)

最初只有InputFragment顯示。當用戶點擊「Calculate」按鈕時,ResultFragment會顯示。這一切運作良好。

ResultFragment有一個「全部清除」按鈕,我想清除InputFragment的字段,並使ResultFragment消失(隱藏,移除或分離,我不關心哪個,只要它變得不可見) 。

但是當你點擊「全部清除」按鈕時它會崩潰。具體而言,致命的NullPointerException發生在clearResult()方法中。

這裏是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:E/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'on空對象引用
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 2015-03-02 19:15:10

+0

如果我的答案可以幫助你,那麼你可以標記它是正確的。 – 2015-03-02 19:17:06

+0

「正確」按鈕在哪裏? (我已經看過1000次之前的評論,但是直到最近纔開始提問,並且不知道如何標記它正確 - 完全不明顯。) – D3VON 2015-03-02 19:21:52

0

你不使用標籤「resultfragtag 「添加InputFragment時。

嘗試增加它的onCreate:

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

謝謝大家!大家都指出使用標籤而不是id。我不知道要添加標籤在交易 - 我把它放在片段的XML。所以這個小提示真的做到了。 (除了輸入和結果片段混合在一起,但如果有人使用這個例子,這很容易看到和糾正)。 – D3VON 2015-03-02 19:11:49

0

用途:

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

取代:

Fragment res_frag = getFragmentManager().findFragmentByTag("resultfragtag"); 
相關問題