programing tip

fragmentpageradapter에서 조각 재사용

itbloger 2020. 10. 31. 09:27
반응형

fragmentpageradapter에서 조각 재사용


조각을 통해 페이지를 표시하는 뷰 페이저가 있습니다. FragmentPagerAdapter하위 클래스 getItem는 낭비처럼 보이는 메서드 에서 새로운 조각을 만듭니다 . 거기 FragmentPagerAdapter에 해당 convertView에서 listAdapter이미 생성 된 조각을 재사용하는 저를 가능하게 할 것이다 그? 내 코드는 다음과 같습니다.

public class ProfilePagerAdapter extends FragmentPagerAdapter {

    ArrayList<Profile> mProfiles = new ArrayList<Profile>();

    public ProfilePagerAdapter(FragmentManager fm) {
        super(fm);
    }

    /**
     * Adding a new profile object created a new page in the pager this adapter is set to.
     * @param profile
     */
    public void addProfile(Profile profile){
        mProfiles.add(profile);
    }

    @Override
    public int getCount() {
        return mProfiles.size();
    }

    @Override
    public Fragment getItem(int position) {
        return new ProfileFragment(mProfiles.get(position));
    }
}

FragmentPagerAdapter이미 Fragments당신을 위해 캐시합니다 . 각 조각은 태그를 할당하고는 FragmentPagerAdapter전화를 시도합니다 findFragmentByTag. 그것은 단지 호출 getItem의 결과가있는 경우 findFragmentByTag입니다 null. 따라서 조각을 직접 캐시 할 필요가 없습니다.


Geoff의 게시물에 대한 부록 :

FragmentFragmentPagerAdapter사용하여 참조를 얻을 수 있습니다 findFragmentByTag(). 태그 이름은 다음과 같이 생성됩니다.

private static String makeFragmentName(int viewId, int index)
{
     return "android:switcher:" + viewId + ":" + index;
}

여기서 viewId는 ViewPager의 ID입니다.

다음 링크를보십시오 : http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104


이 질문을 보는 많은 사람들이 /에 Fragments의해 만들어진 참조 방법을 찾고있는 것 같습니다 . 여기에있는 다른 답변이 사용 하는 내부적으로 생성 된 것에 의존하지 않고 이에 대한 솔루션을 제공하고 싶습니다 .FragmentPagerAdapterFragmentStatePagerAdaptertags

보너스로이 방법은 FragmentStatePagerAdapter. 자세한 내용은 아래 참고를 참조하십시오.


현재 솔루션의 문제점 : 내부 코드에 의존

이 질문과 유사한 질문에 대해 내가 본 많은 솔루션 내부적으로 생성 된 태그를Fragment 호출 FragmentManager.findFragmentByTag()하고 모방하여 기존 대한 참조를 얻는 데 의존합니다 .. 이것의 문제는 당신이 내부 소스 코드에 의존하고 있다는 것입니다. 우리 모두가 알고 있듯이 영원히 동일하게 유지된다는 보장은 없습니다. Google의 Android 엔지니어 는 기존 .NET에 대한 참조를 찾을 수 없도록 코드를 손상 시키는 구조를 쉽게 변경할 수 있습니다 ."android:switcher:" + viewId + ":" + idtagFragments

내부에 의존하지 않는 대체 솔루션 tag

다음 은에 대한 내부 집합에 의존하지 않는 에서 Fragments반환 된에 대한 참조를 가져 오는 방법에 대한 간단한 예입니다 . 핵심은 에서 대신 참조 를 재정의 하고 저장하는 입니다 .FragmentPagerAdaptertagsFragmentsinstantiateItem()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가져올 수도 있습니다 . 참고 : 를 만들 때 설정되지 않기 때문에 적용 되지 않습니다 .tagsFragmentPagerAdapterFragmentStatePagerAdaptertagsFragments

@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;
}

Note that this method does NOT rely on mimicking the internal tag set by FragmentPagerAdapter and instead uses proper APIs for retrieving them. This way even if the tag changes in future versions of the SupportLibrary you'll still be safe.


Don't forget that depending on the design of your Activity, the Fragments you're trying to work on may or may not exist yet, so you have to account for that by doing null checks before using your references.

Also, if instead you're working with FragmentStatePagerAdapter, then you don't want to keep hard references to your Fragments because you might have many of them and hard references would unnecessarily keep them in memory. Instead save the Fragment references in WeakReference variables instead of standard ones. Like this:

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...
}

If the fragment still in memory you can find it with this function.

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

Sample code for v4 support api.


I know this is (theoretically) not an answer to the question, but a different approach.

I had an issue where I needed to refresh the visible fragments. Whatever I tried, failed and failed miserably...

After trying so many different things, I have finally finish this using BroadCastReceiver. Simply send a broadcast when you need to do something with the visible fragments and capture it in the fragment.

If you need some kind of a response as well, you can also send it via broadcast.

cheers


For future readers!

If you are thinking of reusing fragments with viewpager, best solution is to use ViewPager 2, since View Pager 2 make use of RecyclerView.

참고URL : https://stackoverflow.com/questions/6976027/reusing-fragments-in-a-fragmentpageradapter

반응형