我在ViewPager中的片段有问题。在我的应用程序中,我有4个使用FragmentStatePagerAdapter实现的选项卡。 这是我的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,其中有Spinner,带有用于选择另一个图表的选项。当用户选择另一个图表时,通过调用我的SectionsPageAdapter中的fragment0Changed方法,可以在此选项卡中重新加载另一个图表 类。我在https://stackoverflow.com/a/27304530/1573414中找到了这个解决方案。
这是我要在“图表”标签中显示的每个片段中都有的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,but,也没有使用异步方法替换片段,也没有在Activity生命周期方法中调用它。我在微调器的onSelectionChanged方法中进行片段事务。我试过的方法:使用commitNowAllowingStateLoss()并不能使事情变得更好,它只是没有引发异常,片段仍然无法重新加载;将getSupportFragmentManager()参数传递给fragment0Changed方法也没有帮助,但是即使我使用简单的commitNow()方法,这样做也不会引发任何异常。但是有帮助的是,旋转后我选择应用程序的第一个或第二个选项卡,然后转到第四个选项卡(“图表”选项卡),然后我可以切换(重新加载)片段而没有任何问题。有趣的是,切换到第三个选项卡(“日历”选项卡)也无济于事。切换到第三选项卡并返回到第四选项卡后,仍然不会重新加载片段。
答案 0 :(得分:0)
我认为,与Fragment传递侦听器进行通信是Android上的常见错误。 Fragment上的侦听器必须由the Activity or a child Fragment实现。因此,您必须使Activity或Fragment实现NextFragmentListener ...其次,永远不要在ViewPager上引用Fragment,这是在泄漏旧的fragment0
答案 1 :(得分:0)
公共类SubAdapter扩展FragmentStatePagerAdapter {
/ *只是在super()调用中传递行为,因此每次调用resume方法时,您都可以重新加载所需的任何东西 但是您应该使用扩展* /
的子类私有字符串tile_list [];
public SubAdapter (FragmentManager fm, String[] tile_list)
{
super(fm,FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
this.tile_list = tile_list;
}
@Override
public Fragment getItem(int position)
{
Fragment fragment;
switch (position)
{
case 0:
fragment=new new_fragment();
break;
default:
fragment=new new_fragment();
}
return fragment;
}
@Override
public int getCount()
{
return tile_list.length;
}
@Nullable
@Override
public CharSequence getPageTitle(int position)
{
return tile_list[position];
}
}