3 回答

TA貢獻1799條經驗 獲得超9個贊
如果從后堆棧返回片段,它不會重新創建片段,而是會重新使用同一實例,并從onCreateView()片段生命周期開始,請參見片段生命周期。
因此,如果要存儲狀態,則應使用實例變量而不要依賴onSaveInstanceState()。

TA貢獻1780條經驗 獲得超4個贊
與Apple UINavigationController和相比UIViewController,Google在Android軟件架構方面做得不好。與Android有關的文檔Fragment并沒有太大幫助。
當您從FragmentA輸入FragmentB時,現有的FragmentA實例不會被破壞。當您在FragmentB中按Back返回到FragmentA時,我們不會創建新的FragmentA實例?,F有的FragmentA實例onCreateView()將被調用。
關鍵是我們不應該在FragmentA的視圖中再次擴大視圖onCreateView(),因為我們使用的是現有FragmentA的實例。我們需要保存并重用rootView。
以下代碼運行良好。它不僅保持片段狀態,還減少了RAM和CPU負載(因為我們僅在必要時膨脹布局)。我不能相信谷歌的示例代碼和文檔別說但總是夸大布局。
版本1(請勿使用版本1。請使用版本2)
public class FragmentA extends Fragment {
View _rootView;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (_rootView == null) {
// Inflate the layout for this fragment
_rootView = inflater.inflate(R.layout.fragment_a, container, false);
// Find and setup subviews
_listView = (ListView)_rootView.findViewById(R.id.listView);
...
} else {
// Do not inflate the layout again.
// The returned View of onCreateView will be added into the fragment.
// However it is not allowed to be added twice even if the parent is same.
// So we must remove _rootView from the existing parent view group
// (it will be added back).
((ViewGroup)_rootView.getParent()).removeView(_rootView);
}
return _rootView;
}
}
正如評論所提到的,有時在中_rootView.getParent()為null onCreateView會導致崩潰。第2版按照dell116建議刪除了onDestroyView()中的_rootView。已在Android 4.0.3、4.4.4、5.1.0上測試。
版本2
public class FragmentA extends Fragment {
View _rootView;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (_rootView == null) {
// Inflate the layout for this fragment
_rootView = inflater.inflate(R.layout.fragment_a, container, false);
// Find and setup subviews
_listView = (ListView)_rootView.findViewById(R.id.listView);
...
} else {
// Do not inflate the layout again.
// The returned View of onCreateView will be added into the fragment.
// However it is not allowed to be added twice even if the parent is same.
// So we must remove _rootView from the existing parent view group
// in onDestroyView() (it will be added back).
}
return _rootView;
}
@Override
public void onDestroyView() {
if (_rootView.getParent() != null) {
((ViewGroup)_rootView.getParent()).removeView(_rootView);
}
super.onDestroyView();
}
}
警告?。?!
這是哈克!雖然我在我的應用程序中使用它,但是您需要仔細測試和閱讀評論。

TA貢獻1884條經驗 獲得超4個贊
我猜想有另一種方法可以實現您想要的。我沒有說這是一個完整的解決方案,但在我的情況下達到了目的。
我所做的是代替了我剛剛添加目標片段的片段。因此,基本上,您將改為使用add()method replace()。
我還做了什么。我隱藏了當前的片段,并將其添加到堆棧中。
因此,它在不破壞其視圖的情況下將新片段覆蓋在當前片段上。(檢查onDestroyView()是否未調用其方法。加上它可以backstate使我恢復片段。
這是代碼:
Fragment fragment=new DestinationFragment();
FragmentManager fragmentManager = getFragmentManager();
android.app.FragmentTransaction ft=fragmentManager.beginTransaction();
ft.add(R.id.content_frame, fragment);
ft.hide(SourceFragment.this);
ft.addToBackStack(SourceFragment.class.getName());
ft.commit();
AFAIK系統僅onCreateView()在視圖被破壞或未創建時調用。但是這里我們通過不從內存中刪除視圖來保存視圖。因此,它不會創建新視圖。
當您從Destination Fragment返回時,它將彈出最后一個FragmentTransaction刪除的頂部片段,這將使最上面的(SourceFragment's)視圖顯示在屏幕上。
評論:正如我所說,這不是一個完整的解決方案,因為它不會刪除Source片段的視圖,因此比平時占用更多的內存。但還是要達到目的。另外,我們使用完全不同的隱藏視圖機制,而不是替換非傳統的視圖。
因此,這實際上與維護狀態無關,而與維護視圖有關。
- 3 回答
- 0 關注
- 503 瀏覽
添加回答
舉報