gpt4 book ai didi

android - 方向更改后, fragment 对 mActivity 的引用变为空。无效的 fragment 状态维护

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:39:56 24 4
gpt4 key购买 nike

我的应用程序由几个 fragment 组成。到目前为止,我已经将对它们的引用存储在自定义 Application 对象中,但我开始认为我做错了什么。

当我意识到我的 fragment 对 mActivity 的所有引用在方向更改后都变为空时,我的问题就开始了。因此,当我在方向更改后调用 getActivity() 时,会抛出 NullPointerException。在调用 getActivity() 之前,我已经检查过我的 fragment 的 onAttach() 是否被调用,但它仍然返回 null。

以下是我的 MainActivity 的精简版,它是我的应用程序中唯一的 Activity 。

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 的精简版本。我对这一实现的想法是保证在我的应用程序的整个生命周期中每个 fragment 只有一个实例。

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;
}
}

我对有关如何最好地实现多个 fragment 以及如何维护它们的状态的技巧非常感兴趣。供您引用,到目前为止,我的应用程序包含 15 个以上的 fragment 。我做了一些研究,似乎 FragmentManager.findFragmentByTag() 是一个不错的选择,但我未能成功实现它。

除了 mActivity 引用在方向更改后变为 null 之外,我的实现似乎运行良好,这让我相信我也可能有一些内存泄漏问题。

如果您需要查看更多代码,请告诉我。我有意避免包含 fragment 代码,因为我坚信问题与我的 Activity 和 Application 实现有关,但我可能错了。

感谢您的宝贵时间。

最佳答案

My thoughts behind this implementation was to guarantee only one instance of each fragment throughout my application's life cycle

这可能是您遇到困难的部分原因,如果不是全部的话。

在配置更改时,Android 将重新创建您的 fragment ,方法是使用公共(public)零参数构造函数创建一个新实例。因此,您的全局范围 fragment 不会“保证每个 fragment 只有一个实例”。

请删除此自定义 Application 类。请允许 fragment 自然地重新创建,或者如果它们需要为单个 Activity 的生命而活,请使用 setRetainInstance(true)。不要尝试跨 Activity 重用 fragment 。

关于android - 方向更改后, fragment 对 mActivity 的引用变为空。无效的 fragment 状态维护,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15744445/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com