Проблемы при перезагрузке фрагмента в ViewPager - PullRequest
0 голосов
/ 21 сентября 2018

У меня проблема с фрагментами во 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 с вариантами выбора другого графика.И когда пользователь выбирает другую диаграмму, эта другая диаграмма перезагружается на этой вкладке, вызывая методgment0Changed, который есть в моем классе SectionsPageAdapter.Я нашел это решение в 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 () в метод frag0Changed также не помогает, но при этом не возникает никаких исключений, даже если я использую простой метод commitNow ().Но помогает то, что после поворота я выбираю первую или вторую вкладку своего приложения, затем перехожу на четвертую вкладку (вкладка Диаграммы), после чего я могу без проблем переключать (перезагружать) свои фрагменты.Интересно, что переход на третью вкладку (вкладка «Календарь») тоже не помогает.После переключения на третью вкладку и возврата на четвертую вкладку фрагменты переключения по-прежнему не перезагружаются.

1 Ответ

0 голосов
/ 21 сентября 2018

Я думаю, что на Android это распространенная ошибка - общаться с Fragment, передавая слушателя.Слушатель на фрагменте должен быть реализован с помощью Activity или дочернего фрагмента .Поэтому вы должны сделать так, чтобы ваш Activity или Fragment реализовывал NextFragmentListener ... Во-вторых, никогда не делайте ссылку на Fragment в ViewPager, вы пропускаете старый фрагмент0

...