2013-03-09 77 views
2

我有這個活動,我運行一個收集一系列數據的asynctask。這些數據可以用幾種方式表示,爲了簡單起見,我們假設有兩種方法。我希望用戶能夠在這兩種表示(列表視圖和圖形視圖)之間切換。在兩個固定片段之間切換

所以我用我的ListFragment和我的GraphicFragment創建了一個FragmentActivity。

你如何在這兩個之間切換,以便用戶可以來回?我嘗試使用替換,但然後前面的片段被破壞,這是我的興趣,因爲它的引用有我的活動傳遞的數據。 (即,我不想每次用戶在視圖之間切換時重新創建片段)。

我也嘗試隱藏和顯示,但我不能得到它的工作,其中一個片段沒有顯示。

此外,當我旋轉我猜碎片被破壞,因爲我試圖訪問它們時得到一個nullpointerexception。

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

    pBar = (ProgressBar) findViewById(R.id.analyzingProgress); 

    // However, if we're being restored from a previous state, then don't 
    // create the fragment again (please) 
    if (savedInstanceState == null) { 

     firstFragment = new DirListFragment(); 
     secondFragment = new GraphViewFragment(); 

         getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, secondFragment).commit(); 


     fragments= new ArrayList<IFragment>(); 
     fragments.add(firstFragment); 
     fragments.add(secondFragment); 
    } 
} 


    @Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    if(item.getItemId() == R.id.listView){ 

     FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 

     /*transaction.hide(secondFragment);   
     transaction.show(firstFragment);*/ 
     transaction.replace(R.id.fragment_container, firstFragment); 
     transaction.addToBackStack(null); 

     transaction.commit(); 
    } 
    else if(item.getItemId() == R.id.graph){ 
     FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 
     /*transaction.hide(firstFragment); 
     transaction.show(secondFragment);*/ 
     transaction.replace(R.id.fragment_container, secondFragment); 
     transaction.addToBackStack(null); 

     transaction.commit(); 
    } 
    return true; 
} 

問題是當我嘗試訪問片段字段更新他們的數據:

 for(IMyFragment frag: fragments){ 
     frag.updateData(data); 
    } 

我得到一個NullPointerException異常旋轉屏幕後。

此外切換fragmenents時,它們的數據沒有被更新時(即我開始與列表片段,它示出了適當的數據,然後再切換到圖形,沒有數據被示出,再次切換回列表中,沒有任何數據。)

+0

你應該真的添加一些代碼,以便人們能夠更好地幫助你。如果你不想片段被破壞,在片段的'onCreate'中調用'setRetainInstance(true);'。然後在你的活動中使用'replace'。 – Matt 2013-03-09 19:04:02

+0

我發佈了我的oncreate函數和我切換片段的代碼部分 – MichelReap 2013-03-09 19:18:29

+0

您應該查看片段生命週期http://developer.android.com/guide/components/fragments.html#Creating,這是您的問題出現的地方起作用。當您旋轉屏幕時,活動將被銷燬並重新創建,從而破壞碎片。如果在你的片段中設置了'setRetainInstance(true);',所有的信息(變量)仍然會有值,但是你需要重新創建視圖,因爲它們會被銷燬。 – Matt 2013-03-09 20:40:26

回答

2

如果在使用setRetainInstance(true);時字段爲空,那麼您正在您的活動中重新創建它們(碎片)。請確保您設置在onSaveInstanceState()在您的活動東西,所以在onCreate()savedInstanceState將不能爲null,它甚至可以是一個空包或無用的變量,例如:

@Override 
public void onSaveInstanceState(Bundle outstate){ 
    super.onSaveInstanceState(outstate); 
    outstate.putBoolean("stateChanged", true); 
} 

只要確保你加入之前調用超你參數。

另一方面,我個人從未將我的片段存儲在數組中。在我的活動中,我使用FrameLayout作爲片段容器,就像你一樣,如果我需要更新我剛纔調用的東西:getSupportFragmentManager().findFragmentById(R.id.fragment_container).setWhatINeed();這樣我總是會看到可見的片段。

讓我知道更新是如何進行的,我會用任何信息更新這篇文章。

+0

試過,但沒有喜悅。我在數組中做這件事的原因是因爲這些片段是主要活動的觀察者,所以當新數據到達時,他們都會同時得到通知。 – MichelReap 2013-03-10 15:21:39

+0

你現在面臨的具體問題是什麼?仍然像以前一樣?幾個問題:1)你是否檢查確定'savedInstanceState'在方向改變時不爲空(即在'if(savedInstanceState == null)'之後放置'log.d'?2)你是否已經移除了'addToBackStack(null )'電話?你可能會得到一個空指針,因爲你正在將第一個/ secondFragment的本地實例添加到backstack中,然後嘗試更新它,我不相信它是可能的(不能更新棧上的項目) – Matt 2013-03-10 17:33:09

+0

@MichelReap - 數組中的片段,使用標籤創建它們,並將這些標籤放入數組中。然後,您可以始終使用'findFragmentByTag'獲取它們的當前實例 - 在配置更改或其他應用程序中斷後,不必擔心引用過時的引用。 – ToolmakerSteve 2016-09-20 17:02:29