Подтвердить что ты не робот

Просмотр фрагмента в ViewPager не восстанавливается при возобновлении

У меня есть вкладка ActionBar Tabs. Он состоит из 4 вкладок. Все нормально, пока я не перейду от TabbedFragment и не вернусь назад.

Я создаю табуляции следующим образом:

  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final ActionBar actionBar = getActionBar();

        tabs = Lists.newArrayList();
        tabs.add(new TabDefinition<>("Tab 1"));
        tabs.add(new TabDefinition<>("Tab 2"));
        tabs.add(new TabDefinition<>("Tab 3"));
        tabs.add(new TabDefinition<>("Tab 4"));


        for (TabDefinition tab : tabs) {
            actionBar.addTab(actionBar.newTab()
                .setText(tab.text)
                .setTag(tab.tag)
                .setTabListener(this));
        }
    }

И инициализируйте адаптер следующим образом:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.paging_tab_container, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    viewPager = (ViewPager) view.findViewById(R.id.pager);

    viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {

        @Override
        public Fragment getItem(int position) {
            return tabs.get(position).fragment;
        }

        @Override
        public int getCount() {
            return tabs.size();
        }
    });

    viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            getActionBar().setSelectedNavigationItem(position);
        }
    });

    viewPager.setCurrentItem(getActionBar().getSelectedNavigationIndex(), true);
}

При возврате на TabbedFragment выбранную вкладку и 1 рядом с ней не будет никакого содержимого. Просто пустой вид. Но если я выбираю текущее содержимое + 2 фрагмента, загружается. И затем возврат к этому первому фрагменту контента перезагружается.
Например, у меня есть вкладки A, B, C, D. Перед отъездом TabbedFragment я выбрал вкладку A. Возвращаясь к TabbedFragment, я все еще нахожусь на вкладке A, но он пуст. Так же есть вкладка B.
Но при выборе вкладки C она создается и загружается. Возвращаясь к вкладке A, она воссоздана.

В чем может быть проблема?

4b9b3361

Ответ 1

Через некоторое время снова столкнулась с той же проблемой, что и обновление этого вопроса. Если вы используете FragmentStatePagerAdapter, вы должны предоставить FragmentManager через getChildFragmentManager() вместо getFragmentManager(). См. Проблема 55068: ViewPager не обновляет дочерние фрагменты при обратной навигации через стопку

Ответ 2

Итак, при использовании FragmentStatePagerAdapter ваши фрагменты будут уничтожены, если вы перемещаетесь больше, чем один фрагмент. Прочь, поскольку по умолчанию offScreenPageLimit устанавливается по умолчанию, как указано выше.

Обычно этот класс используется для операции с очень большим набором Fragments, то есть нужно прокручивать большое количество просмотров. Если вашему приложению не нужно больше, чем сказать 3-4 вкладки, я бы предложил использовать FragmentPagerAdapter вместо этого, а затем указав ваш offScreenPageLimit на что-то вроде 3, поэтому, если вы доберетесь до четвертой вкладки, все 3 вкладки до этого будут в памяти.

Вот пример кода для проекта на github, который я создал, иллюстрируя, как динамически загружать фрагменты, если вы не хотите добавлять этот offScreenPageLimit.

https://github.com/lt-tibs1984/InterfaceDemo/blob/master/src/com/divshark/interfacedemo/InterfaceDemoMain.java

Пройдите весь этот код в этом классе, и вы увидите, как я динамически загружаю фрагменты, каждый раз, когда мой ViewPager перескакивает. Наиболее заметно внизу.

Вы можете загрузить этот код и использовать его в качестве тестовой базы для того, что вы хотите сделать. Попробуйте добавить setOffScreenPageLimit (2) в метод onCreate() для viewPager и обратите внимание на другое поведение. Чтобы проверить поведение, отредактируйте текст в фрагменте 1. Перейдите в Away и вернитесь назад с помощью этого набора или нет. Вы увидите, когда он будет установлен, текст фрагмента останется тем, к которому вы его измените, поскольку фрагмент никогда не воссоздается.

Пожалуйста, предоставьте дополнительные вопросы, если у вас есть.

GoodLuck

UPDATE

private static final String [] fragmentClasses = {"com.example.project.YourFragment1","com.example.project.YourFragment2","com.example.project.YourFragment3"};



 viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {

    @Override
    public Fragment getItem(int position) {

       Fragment fragmentAtPosition = null;

       // $$$$ This is the Important Part $$$$$
       // Check to make sure that your array is not null, size is greater than 0 , current position is greater than equal to 0, and position is less than length
       if((fragmentClasses != null) && (fragmentClasses.length > 0)&&(position >= 0)&& (position < fragmentClasses.length))
        {
       // Instantiate the Fragment at the current position of the Adapter
        fragmentAtPosition = Fragment.instantiate(getBaseContext(), fragmentClasses[position]);
        fragmentAtPosition.setRetainInstance(true);

       }

        return fragmentAtPosition;
    }

    @Override
    public int getCount() {
        return fragmentClasses.length;
    }
});

Ответ 3

Проблема существует во Фрагментах, которые вы используете в качестве вкладок, я думаю. Кажется, что они ничего не показывают, когда они возобновляются (см. Жизненный цикл фрагмента). "Странная" проблема, что только текущая выбранная вкладка +/- 1 пуста, заключается в том, что offScreenPageLimit вашего ViewPager равен 1 по умолчанию. Все вкладки выше этого порога воссоздаются.

Следовательно, увеличение значения будет - в вашем случае - все ваши вкладки будут пустыми после возобновления. Проверьте свой код фрагмента, какие методы жизненного цикла вы используете для раздувания макета, установки адаптеров и т.д., Потому что это вызывает проблемы.

Ответ 4

Я предполагаю, что это происходит потому, что во время загрузки фрагмента андроида нагрузки current и current + 1, если вы отлаживаете, вы не увидите, что onPause получает вызов для следующего следующего фрагмента.

Вы можете перезагрузить контент программным способом в методе onTabChanged() TabHost.OnTabChangeListener.

Ответ 5

После долгих исследований это сработало для меня. У меня сложный макет с 3 вкладками в фрагменте, который отключается для других фрагментов. Я понял, что ViewpagerAdapter сохранит состояние, даже если вы нажмете кнопку "домой". Моя проблема заключалась в переключении назад и вперед, чтобы исключить элементы представления пользовательского интерфейса дочернего фрагмента и сбой. Ключ состоит в том, чтобы new выйти из ViewpagerAdapter. Добавление нулевой проверки для адаптера сработало для меня. Кроме того, не забудьте выделить setOffscreenPageLimit() для своих нужд. Кроме того, из того, что я понимаю, setRetainInstance(true); не следует использовать для фрагментов, имеющих пользовательский интерфейс, он предназначен для безгласных фрагментов.

В фрагменте, который содержит ваши вкладки:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_tab, container, false);
    tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
    viewPager = (ViewPager) view.findViewById(R.id.viewPager);

    //Important!!! Do not fire the existing adapter!!
    if (viewPagerAdapter == null) {
        viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
        viewPagerAdapter.addFragments(new AFragment(), "A");
        viewPagerAdapter.addFragments(new BFragment(), "B");
        viewPagerAdapter.addFragments(new CFragment(), "C");
    }
    //Allocate retention buffers for three tabs, mandatory
    viewPager.setOffscreenPageLimit(3);
    tabLayout.setupWithViewPager(viewPager);
    viewPager.setAdapter(viewPagerAdapter);

    return view;
}

Ответ 6

Или более просто при навигации по tabbedfragment (при условии, что вы используете намерение, а фрагмент находится в пределах действия):

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

Это сохраняет исходное действие и перемещает его в начало стека, а не воссоздает его, поэтому вам не нужно воссоздавать viewPager.