내 응용 프로그램은 여러 조각으로 구성됩니다. 지금까지는 사용자 지정 Application 개체에 저장된 참조가 있었지만 잘못된 작업을하고 있다고 생각하기 시작했습니다.방향 변경 후 단편의 mActivity에 대한 참조가 null이됩니다. 비효율적 인 조각 상태 유지 보수
오리엔테이션 변경 후 내 조각의 mAtivity에 대한 모든 참조가 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을 제거한 버전입니다. 이 구현의 내 생각은 응용 프로그램의 수명주기 동안 각 조각의 인스턴스를 하나만 보증하는 것이 었습니다.
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()가 좋은 방법 인 것 같지만 성공적으로 구현할 수 없었습니다.
내 구현은 방향 변경 이후에 mAtivity 참조가 null이된다는 사실을 제외하고는 잘 작동하는 것처럼 보였습니다. 이로 인해 일부 메모리 누수 문제가 발생할 수 있다고 생각하게되었습니다.
더 많은 코드가 필요하면 알려 주시기 바랍니다. 나는 문제가 내 Activity와 Application 구현과 관련이 있다고 강력히 믿으므로 조각 코드를 포함하는 것을 의도적으로 피했지만 잘못된 것일 수 있습니다.
감사합니다. 이 구현 뒤에
빠른 응답을 보내 주셔서 감사합니다. 한가지 간단한 질문 : 리소스 목적으로 Android에서 응용 프로그램이 파괴되면 사용자가 응용 프로그램을 다시 시작할 때 응용 프로그램이 파괴되기 전에 마지막으로 본 부분을 보장 할 수 있습니까? 기본 "시작 부분"대신 "시작 부분"이 표시됩니까? 또한 "메뉴"조각이 필요할 때 정확한 위치를 "선택"해야합니다. 선호도가 마음에 들지만, 더 좋은 생각이 있을까요? –
@MortenSalte : "사용자가 내 애플리케이션을 다시 시작할 때 앱이 파괴되기 전에 마지막으로 보았던 부분이 표시됩니다."- onPause() 또는 onStop()에서 프로세스가 종료 된 후에도 유지 될 상태 정보 ('SharedPreferences', file, database). "선호도가 마음에 들지만, 더 좋은 생각이있을 수 있습니까?" - 환경 설정은 이와 같은 일반적인 솔루션이지만 영구 저장소가 작동해야합니다. – CommonsWare