我的應用程序由幾個片段組成。到目前爲止,我已經將它們存儲在自定義應用程序對象中,但我開始認爲我做錯了什麼。當我意識到取向改變後,我的所有片段對mActivity引用變爲空在定向更改後,片段對mA的參考變爲空。無效片段狀態維護
我的問題開始。因此,當我在方向更改後調用getActivity()時,會引發NullPointerException。 我已經在調用getActivity()之前檢查過片段的onAttach(),但它仍然返回null。
以下是我的MainActivity的剝離版本,這是我的應用程序中唯一的活動。
public class MainActivity extends BaseActivity implements OnItemClickListener,
OnBackStackChangedListener, OnSlidingMenuActionListener {
private ListView mSlidingMenuListView;
private SlidingMenu mSlidingMenu;
private boolean mMenuFragmentVisible;
private boolean mContentFragmentVisible;
private boolean mQuickAccessFragmentVisible;
private FragmentManager mManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* Boolean variables indicating which of the 3 fragment slots are visible at a given time
*/
mMenuFragmentVisible = findViewById(R.id.menuFragment) != null;
mContentFragmentVisible = findViewById(R.id.contentFragment) != null;
mQuickAccessFragmentVisible = findViewById(R.id.quickAccessFragment) != null;
if(!savedInstanceState != null) {
if(!mMenuFragmentVisible && mContentFragmentVisible) {
setupSlidingMenu(true);
} else if(mMenuFragmentVisible && mContentFragmentVisible) {
setupSlidingMenu(false);
}
return;
}
mManager = getSupportFragmentManager();
mManager.addOnBackStackChangedListener(this);
final FragmentTransaction ft = mManager.beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if (!mMenuFragmentVisible && mContentFragmentVisible) {
/*
* Only the content fragment is visible, will enable sliding menu
*/
setupSlidingMenu(true);
onToggle();
ft.replace(R.id.contentFragment, getCustomApplication().getSportsFragment(), SportsFragment.TAG);
} else if (mMenuFragmentVisible && mContentFragmentVisible) {
setupSlidingMenu(false);
/*
* Both menu and content fragments are visible
*/
ft.replace(R.id.menuFragment, getCustomApplication().getMenuFragment(), MenuFragment.TAG);
ft.replace(R.id.contentFragment, getCustomApplication().getSportsFragment(), SportsFragment.TAG);
}
if (mQuickAccessFragmentVisible) {
/*
* The quick access fragment is visible
*/
ft.replace(R.id.quickAccessFragment, getCustomApplication().getQuickAccessFragment());
}
ft.commit();
}
private void setupSlidingMenu(boolean enable) {
/*
* if enable is true, enable sliding menu, if false
* disable it
*/
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// launch the fragment that was clicked from the menu
}
@Override
public void onBackPressed() {
// Will let the user press the back button when
// the sliding menu is open to display the content.
if (mSlidingMenu != null && mSlidingMenu.isMenuShowing()) {
onShowContent();
} else {
super.onBackPressed();
}
}
@Override
public void onBackStackChanged() {
/*
* Change selected position when the back stack changes
*/
if(mSlidingMenuListView != null) {
mSlidingMenuListView.setItemChecked(getCustomApplication().getSelectedPosition(), true);
}
}
@Override
public void onToggle() {
if (mSlidingMenu != null) {
mSlidingMenu.toggle();
}
}
@Override
public void onShowContent() {
if (mSlidingMenu != null) {
mSlidingMenu.showContent();
}
}
}
以下是CustomApplication的剝離版本。我在這個實現背後的想法是在整個應用程序的生命週期中只保證每個片段的一個實例。
public class CustomApplication extends Application {
private Fragment mSsportsFragment;
private Fragment mCarsFragment;
private Fragment mMusicFragment;
private Fragment mMoviesFragment;
public Fragment getSportsFragment() {
if(mSsportsFragment == null) {
mSsportsFragment = new SportsFragment();
}
return mSsportsFragment;
}
public Fragment getCarsFragment() {
if(mCarsFragment == null) {
mCarsFragment = new CarsFragment();
}
return mCarsFragment;
}
public Fragment getMusicFragment() {
if(mMusicFragment == null) {
mMusicFragment = new MusicFragment();
}
return mMusicFragment;
}
public Fragment getMoviesFragment() {
if(mMoviesFragment == null) {
mMoviesFragment = new MoviesFragment();
}
return mMoviesFragment;
}
}
我對如何最好地實現多個片段以及如何維護其狀態的提示非常感興趣。爲了您的信息,我的應用程序目前包含15個以上的片段。 我已經做了一些研究,似乎FragmentManager.findFragmentByTag()是一個很好的選擇,但我一直沒能成功實現它。
我的實現似乎工作除了事實方向變化後mActivity引用變得無效,這讓我相信,我可能有一些內存泄漏問題以及良好。
如果您需要查看更多的代碼,請讓我知道。我故意避免包含片段代碼,因爲我堅信問題與我的活動和應用程序實現有關,但我可能是錯的。
謝謝你的時間。
感謝您的快速響應!我將根據需要進行必要的修改:)只是一個簡單的問題:當我的應用程序被Android銷燬以達到資源目的時,我如何保證當用戶重新啓動我的應用程序時,最後一個片段(在應用程序被銷燬之前)顯示,而不是默認的「開始片段」?當發生這種情況時,我還需要使用「菜單」片段來選擇正確的位置。首選項出現在腦海中,但你可能有更好的主意? –
@MortenSalte:「我怎麼能保證,當用戶重新啓動我的應用程序,他的最後一個片段(在應用程序被銷燬之前)顯示在」onPause()'或'onStop()'中,寫出狀態信息('SharedPreferences',文件,數據庫),在你的進程終止之後這些信息將會持續存在。 「首先想到的,但你可能有一個更好的主意?」 - 偏好將是這樣的典型解決方案,但任何持久性商店都應該有效。 – CommonsWare