Mor*_*lte 4 android android-lifecycle android-fragments android-memory
我的应用程序包含几个片段.到目前为止,我已将它们的引用存储在自定义的Application对象中,但我开始认为我做错了.
当我意识到我的片段对mActivity的所有引用在方向改变后变为null时,我的问题就开始了.因此,当我在方向更改后调用getActivity()时,会抛出NullPointerException.我已经检查过我的片段的onAttach()在调用getActivity()之前被调用,但它仍然返回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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是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;
}
}
Run Code Online (Sandbox Code Playgroud)
我对如何最好地实现多个片段以及如何维护其状态的技巧非常感兴趣.为了您的信息,到目前为止,我的应用程序包含15个以上的片段.我做了一些研究,似乎FragmentManager.findFragmentByTag()是一个不错的选择,但我还没能成功实现它.
我的实现似乎工作得很好,除了在方向更改后mActivity引用变为null这一事实让我相信我可能也有一些内存泄漏问题.
如果您需要查看更多代码,请告诉我们.我故意避免包含片段代码,因为我坚信问题与我的Activity和Application实现有关,但我可能错了.
谢谢你的时间.
Com*_*are 11
我在这个实现背后的想法是在整个应用程序的生命周期中只保证每个片段的一个实例
这可能是你困难的根源,如果不是全部的话.
在配置更改时,Android将使用public zero-argument构造函数重新创建片段以创建新实例.因此,您的全局范围片段不会"仅保证每个片段的一个实例".
请删除此自定义Application类.请允许自然地重新创建片段,或者如果它们需要在单个活动的生命中存活,请使用setRetainInstance(true).不要尝试跨活动重用片段.
| 归档时间: |
|
| 查看次数: |
6872 次 |
| 最近记录: |