FragmentPagerAdapter getItem không được gọi


123

Tôi không thể sử dụng lại phân đoạn trong FragmentPagerAdapter .. Sử dụng phương thức killItem (), Nó đang xóa phân đoạn nhưng vẫn không được gọi lại là getItem ()..Chỉ có 2-3 hình ảnh nên tôi đang sử dụng FragmentPagerAdapter Thay vì 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;
    }
}

Và trong FragmentActivity,

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

3
Có lý do cụ thể nào mà bạn làm quá destroyItem()không? Đó là điều không cần thiết.
CommonsWare

để khởi tạo lại, sử dụng FragmentStatePagerAdapter cũng gọi khi bạn ghi đè nó super.destroyItem (vùng chứa, vị trí, đối tượng);
faiziii

Câu trả lời:


306

KISS trả lời:

Sử dụng đơn giản FragmentStatePagerAdapter thay vì FragmentPagerAdapter .

Tôi đã nhận được câu trả lời .. Đầu tiên, tôi nghĩ rằng hãy xóa câu hỏi này vì tôi đang làm một sai lầm rất ngớ ngẩn nhưng câu trả lời này sẽ giúp những người đang đối mặt với cùng một vấn đề mà Thay vào đó FragmentPagerAdapter, hãy sử dụng FragmentStatePagerAdapter.

Như @BlackHatSamurai đã đề cập trong nhận xét:

Lý do điều này hoạt động là vì FragmentStatePagerAdapterphá hủy dưới dạng Các mảnh không được sử dụng. FragmentPagerAdapterkhông làm.


Cảm ơn rất nhiều. Câu trả lời của ông đã giúp tôi rất nhiều.
Priya

1
Ghét trở thành một 'tôi cũng vậy!' post, but yeah>. <Cảm ơn vì đã không xóa câu hỏi.
Paul Ruiz

34
Lý do điều này hoạt động là vì FragmentStatePagerAdapter phá hủy dưới dạng các Đoạn không được sử dụng. FragmentPagerAdapter thì không.
BlackHatSamurai

3
Chỉ để tham khảo trong tương lai cho những người có thể tìm thấy điều này trong khi tìm kiếm một vấn đề cụ thể mà họ đang gặp phải; đọc trên cả FragmentPagerAdapter và FragmentStatePagerAdapter. Chúng hoạt động khác nhau vì một lý do và việc sử dụng cụ thể của bạn có thể yêu cầu cái này hơn cái kia.
Chris Stewart

2
@najibputhawala Tôi đã sử dụng FragmentStatePagerAdapter nhưng vẫn gặp sự cố tương tự. GetItem () không được gọi là
sam_k

168

Sử dụng một FragmentStatePagerAdapterkhông hoàn toàn khắc phục được sự cố của tôi, đây là một sự cố tương tự onCreateViewkhông được gọi cho các đoạn con trong máy nhắn tin dạng xem. Tôi thực sự đang lồng FragmentPagerAdaptervào bên trong của mình một cái khác,Fragment do đó cái FragmentManagerđược chia sẻ trong tất cả chúng và do đó giữ lại các bản sao của các mảnh cũ. Cách khắc phục là thay vào đó cung cấp một phiên bản của phương getChildFragmentManagerthức khởi tạo của FragmentPagerAdaptertrong phân đoạn máy chủ của tôi. Cái gì đó như...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

Các getChildFragmentManager()phương pháp có thể truy cập thông qua một đoạn và điều này làm việc cho tôi, vì nó trả về một tin FragmentManagercho đoạn mà cụ thể cho các tình huống trong đó các mảnh làm tổ là cần thiết. Tôi hy vọng điều này sẽ giúp một ai đó có thể đang gặp phải vấn đề giống tôi !!

  • Tuy nhiên, hãy nhớ rằng để sử dụng getChildFragmentManager()phiên bản API tối thiểu của bạn phải ở mức tối thiểu 17 (4.2), vì vậy điều này có thể làm hỏng bánh răng của bạn. Tất nhiên, nếu bạn đang sử dụng các mảnh từ thư viện hỗ trợ v4, bạn sẽ không sao.

25
Đây là câu trả lời chính xác. Vấn đề là do các phân đoạn được lồng trong các phân đoạn khác nên sử dụng getChildrenFragmentManager () thay vì getFragmentManager ().
shihpeng

Cảm ơn bạn rất nhiều, tôi đã mất mãi mãi để tìm ra câu trả lời này!
Shpongoloid

Tôi đồng ý với @shihpeng. Đây phải là câu trả lời chính xác.
Raymond Lukanta

Đây là một sửa chữa cho tôi. Cảm ơn rất nhiều vì đã gửi câu trả lời
user3734429 30/09/15

Các tài liệu thực sự nên gọi điều này ra trong chương trình đi bộ. Rất thực tế khi một ViewPager sẽ được tải trong một phân đoạn. Cảm ơn vì đã đăng câu trả lời này.
làm việc

7

Ghi đè long getItemId (int position)

FragmentPagerAdapterlưu trữ các mảnh mà nó tạo ra bằng cách sử dụng getItem. Tôi cũng đang gặp phải vấn đề tương tự - ngay cả khi notifyDataSetChanged() getItemđã gọi thì vẫn không được.

Đây thực sự là một tính năng chứ không phải lỗi. Bạn cần ghi đè getItemIdđể có thể sử dụng lại chính xác các phân đoạn của mình. Vì bạn đang loại bỏ các phân đoạn, vị trí của bạn đang thay đổi. Như đã đề cập trong tài liệu:

long getItemId (int position)

Trả lại một số nhận dạng duy nhất cho mặt hàng tại vị trí đã cho.

Việc triển khai mặc định trả về vị trí đã cho. Các lớp con nên ghi đè phương thức này nếu vị trí của các mục có thể thay đổi.

Chỉ cần cung cấp một id duy nhất cho mỗi phân đoạn và bạn đã hoàn tất.

Sử dụng một FragementStatePagerAdapterhoặc trở lại POSITION_NONEtrong int getItemPosition (Object object)là sai. Bạn sẽ không nhận được bất kỳ bộ nhớ đệm nào.


Đây là câu trả lời chính xác. Tôi đã phải cung cấp các id khác nhau cho các đoạn trong getItemIdAND điều chỉnh getItemPositionđể trả về POSITION_NONENẾU cần loại bỏ đoạn. Tôi có một cờ enum cho điều đó. Sau đó getItemsẽ được gọi.
Murat Karagöz

Cảm ơn @ MuratKaragöz vì +50 :)
vedant

5

Tôi đã làm những gì @kanika và @ Jraco11 đã đăng nhưng tôi vẫn gặp sự cố.

Vì vậy, sau rất nhiều thay đổi, tôi đã tìm thấy một cái phù hợp với tôi và được thêm vào FragmentPagerAdapter của tôi mã tiếp theo:

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

Theo những gì tôi đọc, getItemPosition được sử dụng để thông báo cho ViewPager có làm mới một mục hay không và để tránh cập nhật nếu các mục ở vị trí hiển thị không thay đổi.


2

Có hai trường hợp khác nhau: 1.) Bạn có cùng một bố cục cho mọi máy nhắn tin: Trong trường hợp đó, sẽ tốt hơn nếu bạn mở rộng bộ điều hợp tùy chỉnh của mình bằng PagerAdapter và trả về một bố cục duy nhất.

2.) Bạn có bố cục khác nhau cho mọi máy nhắn tin: Trong trường hợp đó, sẽ tốt hơn nếu bạn mở rộng bộ điều hợp tùy chỉnh của mình bằng FragmentStatePagerAdapter và trả về các khung hình khác nhau cho mọi máy nhắn tin.


2

phương pháp getItem()được sử dụng chỉ để tạo ra các mặt hàng mới. Sau khi họ tạo, phương thức này sẽ không được gọi. Nếu bạn cần lấy vật phẩm là đơn vị tiền tệ mà bộ điều hợp sử dụng, hãy sử dụng phương pháp sau:

pagerAdapter.instantiateItem(viewPager, TAB_POS)

0

Tôi nhận thấy rằng việc đặt một trình nghe trên bố cục tab đã ngăn điều này được gọi, có thể là vì chúng chỉ có không gian cho một người nghe tabLayout.setOnTabSelectedListenerthay vì một loạt người nghe.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.