当我 return 回到它时,实现 LoaderCallbacks<Cursor> 的片段(片段内的 ViewPager)的 ListView 是空的
ListView of a Fragment (of a ViewPager inside a Fragment) that implements LoaderCallbacks<Cursor> is empty when I return back to it
当我 return 回到它时,包含 ViewPager 的 Fragment 中的 ListView 是空的。这个 ViewPager 位于 Fragment 内部,因为我使用的是导航抽屉布局。我现在将尝试更详细地解释它:
我正在使用 Navigation Drawer 布局,因此使用了 Fragments。在主要 activity 中,在 onCreate 中,我使用以下代码行设置当前 Fragment:
@Override
protected void onCreate(Bundle savedInstanceState) {
/* More code */
currentFragment = new MainFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
}
MainFragment class 包含一个 ViewPager,它在 onCreateView() 中用这些代码行初始化:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
/* More code */
ViewPager viewPager = (ViewPager) rootView.findViewById(R.id.main_view_pager);
viewPager.setAdapter(new SimpleFragmentPagerAdapter(getActivity(), getActivity().getSupportFragmentManager()));
/* Code for Tablayout */
return rootView;
}
SimpleFragmentPagerAdapter 的片段之一 class 是实现 LoaderManager.LoaderCallbacks
的片段
public class ExpensesFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
private ExpenseCursorAdapter mExpenseCursorAdapter;
private static final int EXPENSE_LOADER = 1;
public ExpensesFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_expenses, container, false);
ListView expensesListView = (ListView) rootView.findViewById(R.id.expenses_list_view);
mExpenseCursorAdapter = new ExpenseCursorAdapter(getContext(), null);
expensesListView.setAdapter(mExpenseCursorAdapter);
getLoaderManager().initLoader(EXPENSE_LOADER, null, this);
return rootView;
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(/* arguments */);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mExpenseCursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mExpenseCursorAdapter.swapCursor(null);
}
}
在第一个 运行 上,一切正常。但是,如果我单击以这种方式实现的导航抽屉菜单,ListView 将变为空:
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.nav_main) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().remove(currentFragment).commit();
currentFragment = new MainFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
} else if (id == R.id.nav_blank) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().remove(currentFragment).commit();
currentFragment = new BlankFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
旋转设备时也存在该问题。不过还是有区别的。当我使用 Navigation Drawer 菜单时,none 的方法 LoaderManager.LoaderCallbacks 被调用,但是当我旋转设备时,onLoadFinished 被调用。
无论如何,问题依旧。知道如何解决吗?
提前致谢。
我找到了解决办法!
基本上,我犯了两个错误。
第一个是关于设备的旋转。
当设备旋转时,Activity 被销毁并再次调用 onCreate。在这种情况下,我不应该调用 new MainFragment()。所以,我在调用之前检查 savedInstanceState 是否为 null,如下所示:
if (savedInstanceState == null) {
currentFragment = new MainFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().
replace(R.id.layout_for_fragments, currentFragment).commit();
}
第二个是片段中的片段。在这种情况下,我不能简单地调用 getSupportFragmentManager()。我应该改为调用 getChildFragmentManager(),仅此而已!
当我 return 回到它时,包含 ViewPager 的 Fragment 中的 ListView 是空的。这个 ViewPager 位于 Fragment 内部,因为我使用的是导航抽屉布局。我现在将尝试更详细地解释它:
我正在使用 Navigation Drawer 布局,因此使用了 Fragments。在主要 activity 中,在 onCreate 中,我使用以下代码行设置当前 Fragment:
@Override
protected void onCreate(Bundle savedInstanceState) {
/* More code */
currentFragment = new MainFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
}
MainFragment class 包含一个 ViewPager,它在 onCreateView() 中用这些代码行初始化:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
/* More code */
ViewPager viewPager = (ViewPager) rootView.findViewById(R.id.main_view_pager);
viewPager.setAdapter(new SimpleFragmentPagerAdapter(getActivity(), getActivity().getSupportFragmentManager()));
/* Code for Tablayout */
return rootView;
}
SimpleFragmentPagerAdapter 的片段之一 class 是实现 LoaderManager.LoaderCallbacks
的片段public class ExpensesFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
private ExpenseCursorAdapter mExpenseCursorAdapter;
private static final int EXPENSE_LOADER = 1;
public ExpensesFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_expenses, container, false);
ListView expensesListView = (ListView) rootView.findViewById(R.id.expenses_list_view);
mExpenseCursorAdapter = new ExpenseCursorAdapter(getContext(), null);
expensesListView.setAdapter(mExpenseCursorAdapter);
getLoaderManager().initLoader(EXPENSE_LOADER, null, this);
return rootView;
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(/* arguments */);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mExpenseCursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mExpenseCursorAdapter.swapCursor(null);
}
}
在第一个 运行 上,一切正常。但是,如果我单击以这种方式实现的导航抽屉菜单,ListView 将变为空:
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.nav_main) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().remove(currentFragment).commit();
currentFragment = new MainFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
} else if (id == R.id.nav_blank) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().remove(currentFragment).commit();
currentFragment = new BlankFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
旋转设备时也存在该问题。不过还是有区别的。当我使用 Navigation Drawer 菜单时,none 的方法 LoaderManager.LoaderCallbacks 被调用,但是当我旋转设备时,onLoadFinished 被调用。
无论如何,问题依旧。知道如何解决吗?
提前致谢。
我找到了解决办法!
基本上,我犯了两个错误。 第一个是关于设备的旋转。 当设备旋转时,Activity 被销毁并再次调用 onCreate。在这种情况下,我不应该调用 new MainFragment()。所以,我在调用之前检查 savedInstanceState 是否为 null,如下所示:
if (savedInstanceState == null) {
currentFragment = new MainFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().
replace(R.id.layout_for_fragments, currentFragment).commit();
}
第二个是片段中的片段。在这种情况下,我不能简单地调用 getSupportFragmentManager()。我应该改为调用 getChildFragmentManager(),仅此而已!