我在ViewPager中遇到了片段的问题。在我的应用程序中,我使用FragmentStatePagerAdapter实现了4个选项卡。 这是我的SectionsPageAdapter.java文件
public class SectionsPageAdapter extends FragmentStatePagerAdapter {
private String fragment0 = "";
private Fragment fragAt0;
private FragmentManager manager;
private String[] tabNames;
Context context;
public SectionsPageAdapter(FragmentManager fm, Context ctx, String lastFrag) {
super(fm);
context = ctx;
tabNames = ctx.getResources().getStringArray(R.array.tabs_name);
this.manager = fm;
this.listener = new fragmentChangeListener();
fragment0 = lastFrag;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return ActivityTypeFragment.newInstance(0);
case 1:
return EventsFragment.newInstance();
case 2:
return CalendarFragment.newInstance();
case 3:
if(fragAt0 == null){
switch(fragment0){
case "Chart":
fragAt0 = ChartFragment.newInstance(listener);
break;
case "Hour":
fragAt0 = HourChartFragment.newInstance(listener);
break;
case "Daily":
fragAt0 = DailyChartFragment.newInstance(listener);
break;
default:
fragAt0 = ChartFragment.newInstance(listener);
}
}
return fragAt0;
default:
return ActivityTypeFragment.newInstance(0);
}
}
@Override
public int getCount() {
return 4;
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return tabNames[position];
}
@Override
public int getItemPosition(@NonNull Object object) {
if (object instanceof ChartFragment && fragAt0 instanceof DailyChartFragment
|| object instanceof HourChartFragment && fragAt0 instanceof DailyChartFragment)
{
return POSITION_NONE;
}
else if (object instanceof DailyChartFragment && fragAt0 instanceof ChartFragment
|| object instanceof HourChartFragment && fragAt0 instanceof ChartFragment){
return POSITION_NONE;
}
else if (object instanceof HourChartFragment && fragAt0 instanceof ChartFragment)
{
return POSITION_NONE;
}
else if (object instanceof ChartFragment && fragAt0 instanceof HourChartFragment
|| object instanceof DailyChartFragment && fragAt0 instanceof HourChartFragment)
{
return POSITION_NONE;
}
return POSITION_NONE;
}
public interface nextFragmentListener {
void fragment0Changed(String newFragmentIdentification, FragmentManager fragmentManager);
}
private nextFragmentListener listener;
private final class fragmentChangeListener implements nextFragmentListener {
@Override
public void fragment0Changed(String fragment, FragmentManager fm) {
fragment0 = fragment;
manager.beginTransaction().remove(fragAt0).commitNow();
switch (fragment) {
case "Chart":
fragAt0 = ChartFragment.newInstance(listener);
break;
case "Daily":
fragAt0 = DailyChartFragment.newInstance(listener);
break;
case "Hour":
fragAt0 = HourChartFragment.newInstance(listener);
break;
}
SectionsPageAdapter.this.notifyDataSetChanged();
}
}
public String getFragmentName()
{
return fragment0;
}
}
在最后一个选项卡中,我有一个片段 - ChartFragment,在其中有一个下拉菜单可以选择另一个图表。当用户选择另一个图表时,通过调用SectionsPageAdapter类中的fragment0Changed方法,在此标签页中重新加载另一个图表。我在https://dev59.com/H2sz5IYBdhLWcg3wsaAN#27304530上找到了这个解决方案。以下是我在每个要出现在Charts选项卡中的片段中拥有的onItemSelected函数。
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (view != null) {
String selectedMenu = ((TextView) view).getText().toString();
if (selectedMenu == getString(R.string.best_appealing_chart)) {
LoadBestAppealingChart();
} else if (selectedMenu == getString(R.string.hour_chart)) {
chartListener.fragment0Changed("Hour", getActivity().getSupportFragmentManager());
}
else
{
chartListener.fragment0Changed("Daily", getActivity().getSupportFragmentManager());
}
}
else {
LoadBestAppealingChart();
}
}
所以,在我旋转设备之前,一切都正常工作,但在那之后选择另一个图表就无法正常工作了。应用程序会抛出异常:
java.lang.IllegalStateException: Fragment host has been destroyed
at android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:2183)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2211)
at android.support.v4.app.BackStackRecord.commitNow(BackStackRecord.java:643).
我已阅读文章https://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html,,但在我的情况下,我没有异步方法来替换片段,也没有在Activity生命周期方法中调用它。我在我的Spinner的onSelectionChanged方法中进行片段事务。我尝试过使用commitNowAllowingStateLoss(),但并没有改善情况,它只是没有抛出异常,片段仍然没有重新加载;将getSupportFragmentManager()参数传递给fragment0Changed方法也没有帮助,但即使我使用简单的commitNow()方法,这样做也不会抛出任何异常。但是,在旋转后选择应用程序的第一个或第二个选项卡,然后转到第四个选项卡(图表选项卡),然后我可以轻松地切换(重新加载)我的片段。有趣的是,切换到第三个选项卡(日历选项卡)也没有帮助。在切换到第三个选项卡并返回第四个选项卡之后,切换片段仍然没有重新加载。