ไม่เรียก FragmentPagerAdapter getItem


123

ฉันไม่สามารถนำ Fragment มาใช้ซ้ำใน FragmentPagerAdapter ได้ .. โดยใช้เมธอด destroyItem () มันกำลังลบแฟรกเมนต์ แต่ยังไม่เรียก getItem () อีก .. มีแค่ 2-3 ภาพดังนั้นฉันจึงใช้ FragmentPagerAdapter แทน FragmentStatePagerAdapter ..

public class ExamplePagerAdapter extends FragmentPagerAdapter {

    ArrayList < String > urls;
    int size = 0;
    public ExamplePagerAdapter(FragmentManager fm, ArrayList < String > res) {
        super(fm);
        urls = res;
        size = urls.size();
    }

    @Override
    public int getCount() {
        if (urls == null) {
            return 0;
        } else {
            return size;
        }

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = new FloorPlanFragment();
        Bundle b = new Bundle();
        b.putInt("p", position);
        b.putString("image", urls.get(position));
        Log.i("image", "" + urls.get(position));
        fragment.setArguments(b);
        return fragment;
    }
}

และใน FragmentActivity

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 

3
มีเหตุผลพิเศษที่คุณลบล้างdestroyItem()หรือไม่? นั่นไม่จำเป็น
CommonsWare

เพื่อเริ่มต้นอีกครั้งใช้ FragmentStatePagerAdapter เรียกเมื่อคุณแทนที่ super.destroyItem (คอนเทนเนอร์ตำแหน่งวัตถุ);
faiziii

คำตอบ:


306

KISS ตอบ:

การใช้งานง่ายFragmentStatePagerAdapterแทนFragmentPagerAdapter

ผมได้คำตอบ .. ประการแรกผมคิดว่าจะลบคำถามนี้เป็นที่ฉันทำผิดพลาดโง่มาก แต่คำตอบนี้จะช่วยให้คนที่ประสบปัญหาเดียวกันว่าแทนที่จะใช้FragmentPagerAdapterFragmentStatePagerAdapter

ดังที่ @BlackHatSamurai กล่าวไว้ในความคิดเห็น:

สาเหตุที่ใช้งานได้เนื่องจากFragmentStatePagerAdapterทำลายเป็น Fragments ที่ไม่ได้ใช้งาน FragmentPagerAdapterไม่.


ขอบคุณมากคำตอบของคุณช่วยฉันได้มาก
Priya

1
เกลียดที่จะเป็น 'ฉันเหมือนกัน!' อีกคน โพสต์ แต่ใช่>. <ขอบคุณที่ไม่ลบคำถาม
Paul Ruiz

34
สาเหตุที่ใช้งานได้เนื่องจาก FragmentStatePagerAdapter ทำลายเป็น Fragments ที่ไม่ได้ใช้งาน FragmentPagerAdapter ไม่ได้
BlackHatSamurai

3
เพื่อใช้อ้างอิงในอนาคตสำหรับผู้ที่อาจพบสิ่งนี้ในขณะที่ค้นหาปัญหาเฉพาะที่พวกเขากำลังประสบอยู่ อ่านทั้ง FragmentPagerAdapter และ FragmentStatePagerAdapter พวกเขาทำงานแตกต่างกันด้วยเหตุผลและการใช้งานเฉพาะของคุณอาจต้องใช้อย่างใดอย่างหนึ่ง
Chris Stewart

2
@najibputhawala ฉันใช้ FragmentStatePagerAdapter แต่ยังคงประสบปัญหาเดียวกัน getItem () ไม่ถูกเรียก
sam_k

168

การใช้ a FragmentStatePagerAdapterไม่สามารถแก้ไขปัญหาของฉันได้อย่างสมบูรณ์ซึ่งเป็นปัญหาที่คล้ายกันซึ่งonCreateViewไม่ได้ถูกเรียกให้ใช้ชิ้นส่วนย่อยในเพจเจอร์มุมมอง ฉันกำลังจริงรังของฉันFragmentPagerAdapterภายในของอีกคนหนึ่งFragmentจึงFragmentManagerถูกใช้ร่วมกันทั่วทั้งหมดของพวกเขาและทำให้การรักษากรณีของชิ้นส่วนเก่า การแก้ไขคือการป้อนอินสแตนซ์ของตัวสร้างgetChildFragmentManagerไปยังตัวสร้างของส่วนFragmentPagerAdapterในโฮสต์ของฉันแทน สิ่งที่ต้องการ...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

getChildFragmentManager()เป็นวิธีการที่สามารถเข้าถึงได้ผ่านส่วนนี้และทำงานสำหรับฉันเพราะมันส่งกลับส่วนตัวFragmentManagerสำหรับส่วนที่เฉพาะสำหรับสถานการณ์ที่เศษรังเป็นสิ่งจำเป็น หวังว่านี่จะช่วยคนที่อาจกำลังมีปัญหาเดียวกันกับฉัน !!

  • อย่างไรก็ตามโปรดทราบว่าในการใช้getChildFragmentManager()เวอร์ชัน API ขั้นต่ำของคุณจะต้องมีอย่างน้อย17 (4.2)ที่สุดดังนั้นจึงอาจทำให้ประแจในเฟืองของคุณ แน่นอนว่าถ้าคุณใช้แฟรกเมนต์จากไลบรารีการสนับสนุน v4 คุณน่าจะโอเค

25
นี่คือคำตอบที่ถูกต้อง ปัญหาเกิดจากการที่ชิ้นส่วนที่ซ้อนอยู่ในส่วนอื่น ๆ ควรใช้ getChildrenFragmentManager () แทน getFragmentManager ()
shihpeng

ขอบคุณมากฉันใช้เวลาตลอดเพื่อค้นหาคำตอบนี้!
Shpongoloid

ฉันเห็นด้วยกับ @shihpeng นี่น่าจะเป็นคำตอบที่ถูกต้อง
Raymond Lukanta

อันนี้เป็นการแก้ไขสำหรับฉัน ขอบคุณมากที่ส่งคำตอบ
user3734429

เอกสารควรเรียกสิ่งนี้ออกมาในการเดินผ่าน เป็นเรื่องจริงอย่างมากที่ ViewPager จะถูกโหลดภายในส่วนย่อย ขอบคุณที่โพสต์คำตอบนี้
ทำงาน

7

แทนที่ long getItemId (int position)

FragmentPagerAdaptergetItemเก็บเศษมันจะสร้างโดยใช้ ฉันประสบปัญหาเดียวกัน - แม้ว่าจะnotifyDataSetChanged() getItemไม่มีการโทรแล้วก็ตาม

นี่เป็นคุณสมบัติไม่ใช่ข้อบกพร่อง คุณต้องลบล้างgetItemIdเพื่อให้สามารถใช้ชิ้นส่วนของคุณซ้ำได้อย่างถูกต้อง เนื่องจากคุณกำลังลบชิ้นส่วนตำแหน่งของคุณจึงเปลี่ยนไป ดังที่กล่าวไว้ในเอกสาร:

long getItemId (int position)

ส่งคืนตัวระบุที่ไม่ซ้ำกันสำหรับรายการในตำแหน่งที่กำหนด

การใช้งานเริ่มต้นจะส่งคืนตำแหน่งที่กำหนด คลาสย่อยควรแทนที่เมธอดนี้หากตำแหน่งของรายการสามารถเปลี่ยนแปลงได้

เพียงแค่ระบุรหัสเฉพาะให้กับแต่ละส่วนและคุณก็เสร็จสิ้น

การใช้FragementStatePagerAdapterหรือกลับPOSITION_NONEเข้าint getItemPosition (Object object)ไม่ถูกต้อง คุณจะไม่ได้รับแคชใด ๆ


อันนี้เป็นคำตอบที่ถูกต้อง ฉันต้องระบุรหัสที่แตกต่างกันสำหรับชิ้นส่วนในgetItemIdและปรับgetItemPositionเพื่อส่งคืนPOSITION_NONEหากควรลบส่วน ฉันมีธง enum สำหรับสิ่งนั้น หลังจากนั้นgetItemจะเรียก.
Murat Karagöz

ขอบคุณ @ MuratKaragözสำหรับ +50 :)
vedant

5

ฉันทำตามที่ @kanika และ @ Jraco11 โพสต์แล้วแต่ยังพบปัญหา

หลังจากมีการเปลี่ยนแปลงมากมายฉันพบสิ่งที่เหมาะกับฉันและถูกเพิ่มไปยัง FragmentPagerAdapter ของฉันในรหัสถัดไป:

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

ตามสิ่งที่ฉันอ่านgetItemPositionใช้เพื่อแจ้งViewPagerว่าจะรีเฟรชรายการหรือไม่และเพื่อหลีกเลี่ยงการอัปเดตหากรายการในตำแหน่งที่มองเห็นไม่ได้เปลี่ยนแปลง


2

มีสองสถานการณ์ที่แตกต่างกัน: 1. ) คุณมีเลย์เอาต์เหมือนกันสำหรับเพจเจอร์ทุกตัว: ในกรณีนี้จะดีกว่าถ้าคุณขยายอะแดปเตอร์ที่กำหนดเองของคุณด้วย PagerAdapter และส่งคืนเค้าโครงเดียว

2. ) คุณมีเลย์เอาต์ที่แตกต่างกันสำหรับเพจเจอร์ทุกตัว: ในกรณีนี้จะดีกว่าถ้าคุณจะขยายอะแดปเตอร์ที่กำหนดเองของคุณโดยใช้ FragmentStatePagerAdapter และส่งคืนแฟรกเมตที่แตกต่างกันสำหรับเพจเจอร์ทุกตัว


2

วิธีgetItem()นี้ใช้เพื่อสร้างไอเท็มใหม่เท่านั้น เมื่อสร้างแล้วจะไม่เรียกวิธีการนี้ หากคุณต้องการรับรายการที่เป็นสกุลเงินที่ใช้โดยอะแดปเตอร์ให้ใช้วิธีนี้:

pagerAdapter.instantiateItem(viewPager, TAB_POS)

0

ฉันพบว่าการตั้งค่า Listener บนเค้าโครงแท็บทำให้ไม่สามารถเรียกสิ่งนี้ได้อาจเป็นเพราะพวกเขามีที่ว่างสำหรับผู้ฟังเพียงคนเดียวtabLayout.setOnTabSelectedListenerแทนที่จะเป็นอาร์เรย์ของผู้ฟัง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.