2011-05-03 89 views
13

編輯怪異片段生命週期誤差

如此看來,我的Fragment保留在它試圖重新初始化它的FragmentManager。仍然不確定爲什麼它不會被Activity破壞。至於加載消息,這在ListView沒有設置適配器時顯示。但是,我在onCreateonResume中設置了適配器項目,因此我不確定爲什麼會顯示此加載屏幕。仍然是開放的這種行爲

原始

我與碎片玩耍,並注意到,在彈出當我改變屏幕的方向一個奇怪的錯誤任何解釋。這個錯誤不應該發生,因爲所有的數據都是在屏幕方向改變時在onCreate中重新創建的。此外,片段onResume()在旋轉後被調用兩次。這是我創建錯誤的步驟以及調試器如何實現這些功能。

  • 活動:的onCreate()
  • 活動:的onResume()
  • 片段:的onResume()
  • 旋轉屏幕
  • 活動:的onCreate()
  • 活動:的onResume()
  • 片段:onResume()(即使Activity.onResume()設置它們,項目爲null)
  • 片段:onResume()(items不爲空,這是爲什麼被稱爲兩次?)

這最後一個片段onResume之後被擊中,平板顯示「載入中...」消息和圖標。爲什麼數據不再顯示在列表中?我的懷疑是onCreate正在創建第二個片段。第一個片段由於方向破壞視圖而丟失數據,第二個片段獲取數據,加載屏幕是第一個沒有數據項的片段,第二個片段被隱藏。我可能是錯的。爲什麼當屏幕像Activity那樣旋轉時,碎片不會全部被破壞?除非它解決這個具體問題,否則請不要批評代碼。我實際上並沒有製作應用,我正在嘗試片段功能。謝謝!

主要活動

private ArrayList<Object> items = new ArrayList<Object>(); 
private MyListFragment mylistFragment; 

public MainActivity() { 
    items.add("Hello"); 
    items.add("World"); 
    items.add("Goodbye"); 
} 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    FragmentManager fm = getFragmentManager(); 
    FragmentTransaction ft = fm.beginTransaction(); 

    mylistFragment = new MyListFragment(); 
    mylistFragment.setItems(items); 

    ft.add(R.id.container, mylistFragment); 
    ft.commit(); 
} 

@Override 
public void onResume() { 
    super.onResume(); 

    mylistFragment.setItems(items); 
    mylistFragment.getListView().setOnItemClickListener(new OnItemClickListener() { 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
      Toast.makeText(MainActivity.this, ((TextView)view).getText(), Toast.LENGTH_LONG).show(); 
     } 

    }); 
} 

名單片段

private List<Object> items = null; 
private Boolean isSet = false; 

@Override 
public void onResume() { 
    super.onResume(); 
    if(!isSet && items != null) { 
     setListAdapter(new ArrayAdapter<Object>(getActivity(), R.layout.item, items)); 
     isSet = true; 
    } 
} 

public void setItems(List<Object> items) { 
    this.items = items; 
    if(this.isResumed()) { 
     setListAdapter(new ArrayAdapter<Object>(getActivity(), R.layout.item, items)); 
     isSet = true; 
    } else { 
     isSet = false; 
    } 
} 

回答

5

FragmentManager將自動重新創建Fragment我。但是,它們中的數據需要重新初始化。因此我的代碼創建了第二個片段。加載屏幕是因爲第一個片段不再有項目的適配器,第二個片段被隱藏。真讓人頭痛,我幾乎認爲FragmentManager應該銷燬Fragments,所以你可以用它們保存的數據重新創建它們。

+1

對不起,但是我沒有看到答案得太清楚......你怎麼收場解決這個問題呢?我得出了和你一樣的結論,但是我找不到解決這個問題的方法。這意味着你如何殺死舊的碎片並使用重新創建的新碎片。 – Maurycy 2012-03-16 06:18:51

+0

如果你想擺脫舊的Fragment並使用新的,使用FragmentTransaction.replace()函數。然後舊的將被替換爲新的。只要知道數據將不得不重新加載。 – Spidy 2012-03-18 05:18:29

0

我相信這就是爲什麼在通過Diane和其他谷歌示例的各種演示中......他們通常會通過靜態方法...和setArguments來幫助初始化初始化。

IIRC,片段創建的東西將調用默認的構造函數來創建,但只知道通過setArguments填充適當的數據。在android開發博客中的示例中,id從列表活動傳遞到細節片段。在setParams被調用之後,fragmentManager應該能夠重新創建它。

文檔似乎對這個主題很少,我希望做的事情正確,所以如果你們有反饋,我會很感激。

0

似乎從支持庫使用FragmentActivity自動保存和恢復實例。因此,只有在savedInstanceStatenull的情況下才進行碎片交易。

例如,在你的FragmentActivityonCreate(),請執行下列操作:

if(savedInstanceState == null){ 
     FragmentManager fragmentManager = getSupportFragmentManager(); 
     fragmentManager.beginTransaction() 
     .replace(R.id.fragment_container, mFragment).commit(); //mFragment is your own defined fragment 
}