私のアプリケーションは、いくつかのフラグメントで構成されています。今まで、カスタム Application オブジェクトに格納されたそれらへの参照を持っていましたが、何か間違ったことをしていると思い始めています。
私の問題は、方向の変更後に mActivity へのすべてのフラグメントの参照が null になることに気付いたときに始まりました。そのため、方向の変更後に 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 の削除されたバージョンです。この実装の背後にある私の考えは、アプリケーションのライフ サイクル全体で各フラグメントのインスタンスを 1 つだけ保証することでした。
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 参照が null になるという事実を除いて、うまく機能しているようです。これにより、メモリ リークの問題もある可能性があると信じることができます。
さらにコードが必要な場合は、お知らせください。問題はアクティビティとアプリケーションの実装に関連していると強く信じているため、意図的にフラグメント コードを含めないようにしましたが、間違っている可能性があります。
御時間ありがとうございます。