문제 요약
참고 :이 답변에서는 FragmentPagerAdapter
소스 코드 를 참조하겠습니다 . 그러나 일반적인 솔루션은 FragmentStatePagerAdapter
.
당신이 당신이 아마 이미 알고 읽는 경우 FragmentPagerAdapter
/ FragmentStatePagerAdapter
생성하기위한 것입니다 Fragments
당신을 위해 ViewPager
,하지만 활동 휴양에 따라 이러한 (앱이 메모리를 회복 죽이는 장치 회전 또는 시스템에서 여부를) Fragments
다시 생성되지 않습니다, 대신 자신을 에서 검색된 인스턴스FragmentManager
. 이제 작업을 수행 Activity
하기 위해 이들 Fragments
에 대한 참조가 필요 하다고 말하십시오 . 내부적으로 설정 했기 때문에 id
또는 tag
for이 생성 되지 않았습니다 . 그래서 문제는 어떻게 그 정보없이 그들에 대한 참조를 얻는 것입니다 ...Fragments
FragmentPagerAdapter
현재 솔루션의 문제점 : 내부 코드에 의존
이 질문과 유사한 질문에 대해 본 많은 솔루션 은 내부적으로 생성 된 태그를Fragment
호출 FragmentManager.findFragmentByTag()
하고 모방하여 기존 에 대한 참조를 얻는 데 의존합니다 .. 이것의 문제는 당신이 내부 소스 코드에 의존하고 있다는 것입니다. 우리 모두가 알고 있듯이 영원히 동일하게 유지된다는 보장은 없습니다. Google의 Android 엔지니어 는 기존 .NET에 대한 참조를 찾을 수 없도록 코드를 손상 시키는 구조를 쉽게 변경할 수 있습니다 ."android:switcher:" + viewId + ":" + id
tag
Fragments
내부에 의존하지 않는 대체 솔루션 tag
다음 은에 대한 내부 집합에 의존하지 않는 에서 Fragments
반환 된에 대한 참조를 가져 오는 방법에 대한 간단한 예입니다 . 핵심은 에서 대신 참조 를 재정의 하고 저장하는 것 입니다 .FragmentPagerAdapter
tags
Fragments
instantiateItem()
getItem()
public class SomeActivity extends Activity {
private FragmentA m1stFragment;
private FragmentB m2ndFragment;
// other code in your Activity...
private class CustomPagerAdapter extends FragmentPagerAdapter {
// other code in your custom FragmentPagerAdapter...
public CustomPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// Do NOT try to save references to the Fragments in getItem(),
// because getItem() is not always called. If the Fragment
// was already created then it will be retrieved from the FragmentManger
// and not here (i.e. getItem() won't be called again).
switch (position) {
case 0:
return new FragmentA();
case 1:
return new FragmentB();
default:
// This should never happen. Always account for each position above
return null;
}
}
// Here we can finally safely save a reference to the created
// Fragment, no matter where it came from (either getItem() or
// FragmentManger). Simply save the returned Fragment from
// super.instantiateItem() into an appropriate reference depending
// on the ViewPager position.
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
// save the appropriate reference depending on position
switch (position) {
case 0:
m1stFragment = (FragmentA) createdFragment;
break;
case 1:
m2ndFragment = (FragmentB) createdFragment;
break;
}
return createdFragment;
}
}
public void someMethod() {
// do work on the referenced Fragments, but first check if they
// even exist yet, otherwise you'll get an NPE.
if (m1stFragment != null) {
// m1stFragment.doWork();
}
if (m2ndFragment != null) {
// m2ndFragment.doSomeWorkToo();
}
}
}
또는 당신이 작업하는 것을 선호하는 경우 tags
클래스 멤버 변수 대신 /를 참조 Fragments
당신은 또한 잡을 수 tags
에 의해 세트를 FragmentPagerAdapter
같은 방식으로 참고 :이 적용되지 않습니다 FragmentStatePagerAdapter
설정되지 않기 때문에 tags
그것을 만들 때 Fragments
.
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
// get the tags set by FragmentPagerAdapter
switch (position) {
case 0:
String firstTag = createdFragment.getTag();
break;
case 1:
String secondTag = createdFragment.getTag();
break;
}
// ... save the tags somewhere so you can reference them later
return createdFragment;
}
이 메서드는 내부 tag
설정 을 모방하는 데 의존하지 FragmentPagerAdapter
않고 대신 적절한 API를 사용하여 검색합니다. 이렇게하면 tag
향후 버전의 변경 사항 SupportLibrary
이 여전히 안전 할 것입니다.
잊지 마십시오 당신의 디자인에 따라 것을 Activity
는 Fragments
당신이 일에 작업을 시도하고 또는 당신이 그렇게함으로써 그것을 위해 계정에 아직 존재하지 않을 수 있습니다 null
귀하의 참조를 사용하기 전에 검사를.
또한 대신 을 사용하는 경우FragmentStatePagerAdapter
하드 참조 Fragments
가 많을 수 있고 하드 참조가 불필요하게 메모리에 유지 될 수 있으므로 하드 참조를 유지하고 싶지 않습니다 . 대신 표준 Fragment
참조 WeakReference
대신 변수에 참조를 저장하십시오 . 이렇게 :
WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment);
// ...and access them like so
Fragment firstFragment = m1stFragment.get();
if (firstFragment != null) {
// reference hasn't been cleared yet; do work...
}