Tôi có hoạt động bằng cách vuốt tab bằng tab ActionBar, dựa trên the android developer example.Trình tải cung cấp kết quả sai phân đoạn
Mỗi tab sẽ hiển thị Phân đoạn và mỗi Phân đoạn (thực sự, một SherlockFragment) sẽ tải một loại yêu cầu api từ xa khác thông qua AsyncTaskLoader tùy chỉnh.
Vấn đề là nếu bạn nhấn vào một tab để di chuyển 2 tab/trang trong khi đoạn cho tab bạn đang rời (đoạn cũ) đang tải kết quả, kết quả đó sẽ được phân phối tới đoạn cho tab bạn di chuyển đến (đoạn mới). Trong trường hợp của tôi, điều này dẫn đến một ClassCastException, vì kết quả mong đợi là các kiểu không tương thích.
Trong mã, các ý chính của tình trạng này là:
Máy bốc hàng:
public class FooLoader extends AsyncTaskLoader<Foo>
public class BarLoader extends AsyncTaskLoader<Bar>
Những mảnh vỡ: Mã quản lý
public class FooFragment extends Fragment implements LoaderManager.LoaderCallbacks<Foo> {
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
}
public Loader<Foo> onCreateLoader(int id, Bundle args) { return new FooLoader(); }
...
}
public class BarFragment extends Fragment implements LoaderManager.LoaderCallbacks<Bar> {
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
}
public Loader<Bar> onCreateLoader(int id, Bundle args) { return new BarLoader(); }
...
}
Tab là như trong the aforementioned example. Có một tab thứ ba ở giữa các tab Foo và Bar (gọi là Baz). Khi chúng ta bỏ qua từ tab Foo đến tab Bar bằng cách nhấn vào tab Bar sau khi FooFragment đã gọi initLoader trên LoaderManager của nó nhưng trước khi FooFragment.onLoadFinished được gọi, chúng tôi kết thúc với một ClassCastException trên một cuộc gọi tới BarFragment.onLoadFinished:
java.lang.ClassCastException: com.example.Foo cannot be cast to com.example.Bar
at com.example.BarFragment.onLoadFinished(BarFragment.java:1)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:427)
at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:562)
at com.example.BarFragment.onCreate(BarFragment.java:36)
at android.support.v4.app.Fragment.performCreate(Fragment.java:1437)
...
Tại sao điều này xảy ra và làm cách nào để ngăn chặn? Nó trông giống như các bản ghi gỡ lỗi giống như LoaderManager đang được tái sử dụng trong đoạn Bar (mặc dù đoạn Baz có riêng của nó), nhưng tôi không biết tại sao điều đó lại xảy ra.
Cập nhật: Sử dụng ID trình tải khác nhau trong mỗi đoạn không loại bỏ sự cố (hoặc dường như - tôi thực sự không biết tại sao) nhưng tôi không muốn làm điều này. Trong một trong những mảnh tôi thực sự tạo ra ID động và không muốn giả định sẽ không có va chạm. Ngoài ra, giải pháp đó là lạ đối với tôi - ID trình tải phải là cục bộ cho từng đoạn (nếu không, tại sao tôi có thể có Trình tải có cùng ID trong các đoạn khác nhau trong các trường hợp bình thường?)
Có vẻ như tôi cũng có thể loại bỏ sự cố gọi setOffscreenPageLimit(2)
trên ViewPager của tôi, để chế độ xem Foo không bị hủy khi chúng tôi chuyển sang chế độ xem Thanh. Nhưng đây là giải pháp thay thế, không phải là giải pháp chung.
Toàn bộ mã: Tôi đã tạo một example application demonstrating the error. Nó bao gồm một kịch bản monkeyrunner để buộc lỗi (mặc dù nó có thể không hoạt động cho tất cả các kích cỡ màn hình).
Bạn có thể đăng toàn bộ mã cho một trong các trình tải không. – yarian
Hãy thử chuyển cuộc gọi của bạn sang 'initLoader' thành' onActivityCreated' thay vì 'onCreate'. –
Có vẻ như nó giải quyết được vấn đề. Cảm ơn! – jgiles