phiên bản ngắn:onResume() không được gọi vào ViewPager đoạn khi sử dụng Loader tùy chỉnh
Tôi có một mảnh duy trì một ViewPager
để hiển thị hai mảnh khác, chúng ta hãy gọi chúng FragmentOne
và FragmentTwo
. Khi bắt đầu ứng dụng FragmentOne
hiển thị và FragmentTwo
tắt màn hình, chỉ hiển thị khi một lần vuốt chế độ xem sang trái.
Thông thường onStart()
và onResume()
được gọi ngay lập tức cho cả hai phân đoạn ngay khi ứng dụng được bắt đầu.
Vấn đề tôi gặp phải là khi FragmentOne
bắt đầu tùy chỉnh Loader
thì onResume()
không được gọi trên FragmentTwo
cho đến khi hiển thị hoàn toàn.
Câu hỏi:
Đây có phải là một vấn đề với mã của tôi hoặc một lỗi trong các thư viện hỗ trợ Android? (Vấn đề không xảy ra với bản sửa đổi 12 của thư viện, nó bắt đầu với bản sửa đổi 13.)
Nếu đó là lỗi trong các lần xem lại 13 và 18, có cách giải quyết khác không?
Có điều gì sai với tùy chỉnh Loader
của tôi không?
phiên bản Long:
tôi đã xây dựng một ứng dụng mẫu đó chứng tỏ vấn đề. Tôi đã cố gắng để giảm mã số đến mức tối thiểu nhưng nó vẫn còn rất nhiều vì vậy xin vui lòng chịu với tôi.
Tôi có một MainActivity
tải MainFragment
tạo ViewPager
. Điều quan trọng đối với ứng dụng của tôi là ViewPager được duy trì bởi một Fragment thay vì Activity.
MainFragment
tạo một FragmentPagerAdapter
do đó tạo ra các đoạn FragmentOne
và FragmentTwo
.
Hãy bắt đầu với các bit thú vị, hai mảnh:
FragmentOne
là một ListFragment
có sử dụng một tùy chỉnh Loader
để tải nội dung:
public class FragmentOne extends ListFragment implements LoaderCallbacks<List<String>> {
private ArrayAdapter<String> adapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1);
setListAdapter(adapter);
setEmptyText("Empty");
}
@Override
public void onResume() {
super.onResume();
// initializing the loader seems to cause the problem!
getLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<List<String>> onCreateLoader(int id, Bundle args) {
return new MyLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<List<String>> loader, List<String> data) {
adapter.clear();
adapter.addAll(data);
}
@Override
public void onLoaderReset(Loader<List<String>> loader) {
adapter.clear();
}
public static class MyLoader extends AsyncTaskLoader<List<String>> {
public MyLoader(Context context) {
super(context);
}
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
public List<String> loadInBackground() {
return Arrays.asList("- - - - - - - - - - - - - - - - - - - foo",
"- - - - - - - - - - - - - - - - - - - bar",
"- - - - - - - - - - - - - - - - - - - baz");
}
}
}
Nó là Loader
điều đó dường như gây ra các vấn đề . Nhận xét ra dòng initLoader làm cho chu kỳ sống của vòng quay hoạt động như mong đợi một lần nữa.
FragmentTwo
thay đổi nội dung của nó dựa trên việc onResume()
đã được gọi hay không:
public class FragmentTwo extends Fragment {
private TextView text;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
text = new TextView(container.getContext());
text.setText("onCreateView() called");
return text;
}
@Override
public void onResume() {
super.onResume();
Log.i("Fragment2", "onResume() called");
text.setText("onResume() called");
}
}
Và đây là phần còn lại nhàm chán của mã này.
MainActivity
:
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment fragment = new MainFragment();
getSupportFragmentManager().beginTransaction().add(R.id.container, fragment).commit();
}
}
Layout activity_main
:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MainFragment
:
public class MainFragment extends Fragment {
private ViewPager viewPager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.frag_master, container, false);
viewPager = (ViewPager) layout.findViewById(R.id.view_pager);
return layout;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
viewPager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));
}
private static final class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public int getCount() {
return 2;
}
@Override
public Fragment getItem(int position) {
if (position == 0)
return new FragmentOne();
else
return new FragmentTwo();
}
}
}
Layout frag_master
:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Tôi đang gặp chính xác cùng một vấn đề như bạn đang có, bạn tác phẩm giải pháp nhưng với hiệu suất - giá chậm trễ. Làm thế nào bạn tìm thấy giải pháp? –
tại sao bạn đăng nó vào trình xử lý? – Xenione
@Xenione Đây chỉ là giải pháp thay thế, nhưng nó an toàn để sử dụng. Đây là suy nghĩ của tôi. Chúng ta thấy rằng việc gọi initLoader() trong Fragment đầu tiên ngăn cản việc gọi onResume() trên các đoạn khác (có thể là do lỗi trong thư viện). Trong không có cuộc gọi như vậy, tất cả các phương thức onResume() được gọi trong một khung thực thi duy nhất. Về mặt logic, nếu chúng ta muốn khung công tác gọi phương thức onResume() trong tất cả các Fragments, chúng ta phải tránh gọi initLoader(). Về mặt logic, để khởi tạo bộ nạp ngay sau khi onResume() chúng ta cần thực hiện nó trong khung thực hiện tiếp theo. Đây là nơi handler.post() giúp rất nhiều. –