답변:
에서 단편 가이드 FragmentList의 예를 찾을 수 있습니다 :
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("curChoice", mCurCheckPosition);
}
나중에 다음과 같이 사용할 수 있습니다.
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// Restore last state for checked position.
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
}
}
나는 Fragments의 초보자이지만 문제의 해결책처럼 보입니다.;) BackActivation에서 조각이 반환 된 후 OnActivityCreated가 호출됩니다.
onSaveInstanceState해당 활동이 종료 될 때만 호출됩니다.
조각의은 onSaveInstanceState(Bundle outState)자체 부착 된 조각에 조각의 활동 호출을하지 않는 한 호출되지 않습니다. 따라서이 메소드는 무언가 (일반적으로 회전)가 활동을 강제 SaveInstanceState하고 나중에 복원 할 때까지 호출되지 않습니다 . 그러나 하나의 활동과 그 안에 많은 조각이 있고 (집중적으로 사용 replace) 응용 프로그램이 한 방향으로 만 실행되는 경우 onSaveInstanceState(Bundle outState)오랫동안 호출되지 않을 수 있습니다.
가능한 세 가지 해결 방법을 알고 있습니다.
첫번째:
중요한 데이터를 보유하기 위해 조각의 인수를 사용하십시오.
public class FragmentA extends Fragment {
private static final String PERSISTENT_VARIABLE_BUNDLE_KEY = "persistentVariable";
private EditText persistentVariableEdit;
public FragmentA() {
setArguments(new Bundle());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, null);
persistentVariableEdit = (EditText) view.findViewById(R.id.editText);
TextView proofTextView = (TextView) view.findViewById(R.id.textView);
Bundle mySavedInstanceState = getArguments();
String persistentVariable = mySavedInstanceState.getString(PERSISTENT_VARIABLE_BUNDLE_KEY);
proofTextView.setText(persistentVariable);
view.findViewById(R.id.btnPushFragmentB).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getFragmentManager()
.beginTransaction()
.replace(R.id.frameLayout, new FragmentB())
.addToBackStack(null)
.commit();
}
});
return view;
}
@Override
public void onPause() {
super.onPause();
String persistentVariable = persistentVariableEdit.getText().toString();
getArguments().putString(PERSISTENT_VARIABLE_BUNDLE_KEY, persistentVariable);
}
}
두 번째이지만 덜 간단한 방법-싱글 톤으로 변수를 보유하십시오.
세 번째- replace()조각화 하지 않고 대신 add()/ show()/를 hide()사용하십시오.
Fragment.onSaveInstanceState()호출되지 않은 최고의 솔루션 . 목록보기의 항목 또는 해당 ID 만 포함하여 자신의 데이터를 인수에 저장하기 만하면됩니다 (다른 중앙 집중식 데이터 관리자가있는 경우). 목록보기의 위치를 저장할 필요가 없습니다-자동으로 저장되고 복원되었습니다.
String persistentVariable = mySavedInstanceState.getString(PERSISTENT_VARIABLE_BUNDLE_KEY);항상 null입니다. 뭐가 문제 야?
getArguments()확실히 ViewPager에서 중첩 된 조각을 포함하여, 길을 가야하는 것입니다. 나는 1 액티비티를 사용하고 많은 조각을 입 / 출력하며 이것은 완벽하게 작동합니다. 다음은 제안 된 솔루션을 조사하기위한 간단한 테스트입니다. 1) Fragment A에서 Fragment B로 이동하십시오. 2) 장치 방향을 두 번 변경하십시오. 3) 장치의 뒤로 버튼을 누릅니다.
setArguments(new Bundle());이전 번들을 호출하고 덮어 씁니다. 따라서 조각을 한 번만 만든 다음 매번 새 인스턴스를 만드는 대신이 인스턴스를 사용하십시오.
ViewPager를 사용하여 Fragments를 사용하면 매우 쉽습니다. 이 메소드 만 호출하면 setOffscreenPageLimit()됩니다.
문서에 따라 :
유휴 상태의보기 계층 구조에서 현재 페이지의 한쪽에 유지해야하는 페이지 수를 설정하십시오. 이 한계를 초과하는 페이지는 필요할 때 어댑터에서 다시 작성됩니다.
뷰를 한 번만 부 풀리십시오.
예를 들면 다음과 같습니다.
public class AFragment extends Fragment {
private View mRootView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(mRootView==null){
mRootView = inflater.inflate(R.id.fragment_a, container, false);
//......
}
return mRootView;
}
}
Fragment는 루트 뷰가 그렇게하지 않을 것이라고 말합니다. 일부 GC- 루트 요소에 의한 참조는 전역 정적 속성과 같이 비 ui 스레드 변수입니다. Fragment가비지 수집 할 수 있도록 인스턴스는, GC-루트가 아닌. 루트 뷰도 마찬가지입니다.
나는 이것과 매우 비슷한 문제로 일했다. 나는 종종 이전 조각으로 돌아갈 것이라는 것을 알았으므로 조각 .isAdded()이 사실 인지 확인했으며 , 그렇다면 조각 을 만드는 것보다 transaction.replace()그냥 수행합니다 transaction.show(). 이렇게하면 프래그먼트가 이미 스택에있는 경우 프래그먼트가 다시 생성되지 않습니다.
Fragment target = <my fragment>;
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if(target.isAdded()) {
transaction.show(target);
} else {
transaction.addToBackStack(button_id + "stack_item");
transaction.replace(R.id.page_fragment, target);
}
transaction.commit();
명심해야 할 또 다른 사항은 프래그먼트 자체의 자연스러운 순서를 유지하면서 방향 (구성) 변경시 파기 및 재 작성되는 활동 자체를 처리해야 할 수도 있다는 것입니다. 노드의 AndroidManifest.xml에서이 문제를 해결하려면 다음을 수행하십시오.
android:configChanges="orientation|screenSize"
Android 3.0 이상에서는 screenSize분명히 필요합니다.
행운을 빕니다
android:configChanges=everythinYouCanThinkOf|moreThingsYouFoundOnTheInternets매니페스트를 추가하지 마십시오 . 대신 다음과 같이 상태를 저장하고 복원하는 방법을 배우십시오. speakerdeck.com/cyrilmottier/…
내가 찾은 최고의 솔루션은 다음과 같습니다.
onSavedInstanceState () : 활동이 종료 될 때 항상 조각 내에서 호출됩니다 (활동을 다른 것으로 이동하거나 구성 변경). 따라서 동일한 액티비티에서 여러 조각을 호출하는 경우 다음 접근법을 사용해야합니다.
프래그먼트의 OnDestroyView ()를 사용하여 전체 객체를 해당 메소드에 저장하십시오. 그런 다음 OnActivityCreated () : 객체가 null인지 확인합니다 (이 메소드는 매번 호출하기 때문에). 이제 여기에서 객체의 상태를 복원하십시오.
항상 작동합니다!
목록보기가 포함 된 조각에 하이브리드 접근법을 사용했습니다. 현재 조각을 바꾸지 않고 새로운 조각을 추가하고 현재 조각을 숨기므로 성능이 좋은 것 같습니다. 내 조각을 호스팅하는 활동에 다음과 같은 방법이 있습니다.
public void addFragment(Fragment currentFragment, Fragment targetFragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(0,0,0,0);
transaction.hide(currentFragment);
// use a fragment tag, so that later on we can find the currently displayed fragment
transaction.add(R.id.frame_layout, targetFragment, tag)
.addToBackStack(tag)
.commit();
}
목록 항목을 클릭 / 탭 할 때마다 (목록보기가 포함 된) 조각 에서이 방법을 사용하므로 세부 정보 조각을 시작 / 표시해야합니다.
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
SearchFragment currentFragment = (SearchFragment) fragmentManager.findFragmentByTag(getFragmentTags()[0]);
DetailsFragment detailsFragment = DetailsFragment.newInstance("some object containing some details");
((MainActivity) getActivity()).addFragment(currentFragment, detailsFragment, "Details");
getFragmentTags()새 조각을 추가 할 때 다른 조각에 대한 태그로 사용하는 문자열 배열을 반환합니다 ( 위의 transaction.add방법의 addFragment메소드 참조).
목록보기가 포함 된 조각에서는 onPause () 메서드 에서이 작업을 수행합니다.
@Override
public void onPause() {
// keep the list view's state in memory ("save" it)
// before adding a new fragment or replacing current fragment with a new one
ListView lv = (ListView) getActivity().findViewById(R.id.listView);
mListViewState = lv.onSaveInstanceState();
super.onPause();
}
그런 다음 프래그먼트의 onCreateView (실제로 onCreateView에서 호출되는 메소드에서)에서 상태를 복원합니다.
// Restore previous state (including selected item index and scroll position)
if(mListViewState != null) {
Log.d(TAG, "Restoring the listview's state.");
lv.onRestoreInstanceState(mListViewState);
}
활동에서 다른 조각으로 필드 값을 유지하는 간단한 방법
프래그먼트 인스턴스 생성 및 교체 및 제거 대신 추가
FragA fa= new FragA();
FragB fb= new FragB();
FragC fc= new FragB();
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmnt_container, fa);
fragmentTransaction.add(R.id.fragmnt_container, fb);
fragmentTransaction.add(R.id.fragmnt_container, fc);
fragmentTransaction.show(fa);
fragmentTransaction.hide(fb);
fragmentTransaction.hide(fc);
fragmentTransaction.commit();
그런 다음 조각을 다시 추가하거나 제거하는 대신 조각을 표시하고 숨기십시오.
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.hide(fa);
fragmentTransaction.show(fb);
fragmentTransaction.hide(fc);
fragmentTransaction.commit()
;
private ViewPager viewPager;
viewPager = (ViewPager) findViewById(R.id.pager);
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}