popBackStack 후 ViewPager의 조각이 복원되지 않음
문제
Fragment는 다른 조각에서 반환 된 후 호스팅 ViewPager에 다시 연결되지 않습니다.
상태
레이아웃에 ViewPager가있는 Fragment를 호스팅하는 하나의 활동 ( PageListFragment
아래 예 참조). ViewPager는 FragmentStateViewPagerAdapter로 채워집니다. 호출기 내부에서 호스팅되는 단일 프래그먼트 ( PageFragment
아래 예)는 새로운 페이지 세트를 포함하는 하위 페이지 목록을 열 수 있습니다.
행동
뒤로 버튼을 누르지 않는 한 모두 정상적으로 작동합니다. 사용자가 하위 페이지 목록 중 하나를 닫으면 이전 목록이 다시 생성되지만 이전에 표시된 페이지는 표시되지 않습니다. 상위 페이지 목록의 다른 페이지를 스 와이프해도 여전히 작동합니다.
암호
샘플 애플리케이션은 github 에서 찾을 수 있습니다 .
활동
public class MainActivity extends FragmentActivity {
private static final String CURRENT_FRAGMENT = MainActivity.class.getCanonicalName() + ".CURRENT_FRAGMENT";
public static final String ARG_PARENTS = "Parents";
public void goInto(String mHostingLevel, String mPosition) {
Fragment hostingFragment = newHostingFragment(mHostingLevel, mPosition);
addFragment(hostingFragment);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addBaseFragment();
}
private void addBaseFragment() {
Fragment hostingFragment = newHostingFragment("", "");
addFragment(hostingFragment);
}
private Fragment newHostingFragment(String mHostingLevel, String oldPosition) {
Fragment hostingFragment = new PageListFragment();
Bundle args = new Bundle();
args.putString(ARG_PARENTS, mHostingLevel + oldPosition +" > ");
hostingFragment.setArguments(args);
return hostingFragment;
}
private void addFragment(Fragment hostingFragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentSpace, hostingFragment, CURRENT_FRAGMENT);
transaction.addToBackStack(null);
transaction.commit();
}
}
PageListFragment
public class PageListFragment extends Fragment {
private String mParentString;
public PageListFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_hosting, container, false);
}
@Override
public void onResume() {
mParentString = getArguments().getString(MainActivity.ARG_PARENTS);
ViewPager viewPager = (ViewPager) getView().findViewById(R.id.viewPager);
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString));
super.onResume();
}
private static class SimpleFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
private String mHostingLevel;
public SimpleFragmentStatePagerAdapter(FragmentManager fm, String hostingLevel) {
super(fm);
this.mHostingLevel = hostingLevel;
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
PageFragment pageFragment = new PageFragment();
Bundle args = new Bundle();
args.putString(MainActivity.ARG_PARENTS, mHostingLevel);
args.putInt(PageFragment.ARG_POSITION, position);
pageFragment.setArguments(args);
return pageFragment;
}
@Override
public int getCount() {
return 5;
}
}
}
PageFragment
public class PageFragment extends Fragment {
public static final String ARG_POSITION = "Position";
private String mHostingLevel;
private int mPosition;
public PageFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.fragment_page, container, false);
setupTextView(contentView);
setupButton(contentView);
return contentView;
}
private void setupTextView(View contentView) {
mPosition = getArguments().getInt(ARG_POSITION);
mHostingLevel = getArguments().getString(MainActivity.ARG_PARENTS);
TextView text = (TextView) contentView.findViewById(R.id.textView);
text.setText("Parent Fragments " + mHostingLevel + " \n\nCurrent Fragment "+ mPosition);
}
private void setupButton(View contentView) {
Button button = (Button) contentView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openNewLevel();
}
});
}
protected void openNewLevel() {
MainActivity activity = (MainActivity) getActivity();
activity.goInto(mHostingLevel, Integer.toString(mPosition));
}
}
오랜 조사 끝에 조각 관리자의 문제로 판명되었습니다.
조각 트랜잭션 위에있는 것과 같은 구조를 사용하여 조각을 페이지 목록에 다시 연결하면 자동으로 삭제됩니다. 기본적으로 원인이되는 동일한 문제입니다
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
FragmentPager 내부의 조각을 변경하려고 할 때.
이 오류의 문제와 동일한 솔루션이 여기에도 적용됩니다. FragmentStatePagerAdapter를 구성 할 때 올바른 자식 조각 관리자를 제공합니다.
대신에
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString));
하다
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getChildFragmentManager(),mParentString));
참조 : github
Paul이 언급하지 않은 것은 getChildFragmentManager 를 사용 하면 "뒤로 누를 때 빈 화면"문제가 발생한다는 것입니다.
내 경우 계층 구조는 다음과 같습니다.
MainActivity
-> MainFragment
-> TabLayout
+ ViewPager
-> AccountsFragment
+ SavingsFragment
+ InvestmentsFragment
등
내가 가진 문제는 내가 사용할 수 없다고했다 childFragmentManager
항목에 클릭하는 이유 Account view
(의 내부에 하나의 존재 Fragment
의의 ViewPager
필요를) 대체 할 MainFragment
예를 전체 화면을.
사용 MainFragment
의 호스트 Fragment
즉, 통과는 getFragmentManager()
일 교체,하지만 백 스택 터지는 때, 나는이 화면으로 돌아가 셨습니다을 사용할 수 :
이것은 ViewPager
비어 있는 레이아웃 검사기를 보면 알 수 있습니다 .
복원 된 Fragment
s를 보면 View
복원되었지만 팝된 상태의 계층 구조와 일치하지 않는 것을 알 수 있습니다. 최소한의 영향을 미치고 강제로 다시 작성하지 않기 위해 다음 변경 사항으로 Fragment
다시 작성 FragmentStatePagerAdapter
했습니다.
전체 코드를 복사 FragmentStatePagerAdapter
하고 변경했습니다.
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
...
}
와
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
mCurTransaction.detach(f);
mCurTransaction.attach(f);
return f;
}
}
...
}
이렇게하면 복원 된 파일 Fragment
이에 다시 연결 되었는지 효과적으로 확인할 수 ViewPager
있습니다.
모든 페이지 조각을 삭제하여 나중에 다시 추가 할 수 있습니다.
페이지 조각은 FragmentStatePagerAdapter가 다시 연결하지 않기 때문에 뷰 페이저 화면으로 돌아갈 때 연결되지 않습니다. 해결 방법으로 popbackstack ()이 호출 된 후 viewpager에서 모든 조각을 삭제하면 초기 코드에서 다시 추가 할 수 있습니다.
[이 예제는 Kotlin으로 작성되었습니다.]
//Clear all fragments from the adapter before they are re-added.
for (i: Int in 0 until adapter.count) {
val item = childFragmentManager.findFragmentByTag("f$i")
if (item != null) {
adapter.destroyItem(container!!, i, item)
}
}
참조 URL : https://stackoverflow.com/questions/16600156/fragment-in-viewpager-not-restored-after-popbackstack
'UFO ET IT' 카테고리의 다른 글
배열 변경시 $ watch가 트리거되지 않음 (0) | 2021.01.05 |
---|---|
Github SSH 구성 (0) | 2021.01.05 |
Android Studio 업데이트 후 Gradle 빌드 오류 (0) | 2021.01.05 |
Resharper와 함께 VS 코드 스 니펫 사용 (0) | 2021.01.05 |
this.getClass (). getClassLoader (). getResource (“…”) 및 NullPointerException (0) | 2021.01.05 |