Как обрабатывать AsyncTask во фрагментах ActionBarActivity при использовании ViewPager?

Я использую ActionBarActivity для создания 5 вкладок. Я использовал ViewPager для прокрутки между 5 вкладками с помощью SectionsPagerAdapter, который расширяет FragmentPagerAdapter. На каждой вкладке есть фрагмент с асинхронной задачей, вызываемой в методе oncreateview. Когда я нахожусь в одном фрагменте, вызывается асинтаск в другом фрагменте.

Я попытался использовать всплывающие сообщения в методе oncreateview для каждого фрагмента вместо асинхронной задачи. Но неправильные всплывающие сообщения запускаются в неправильном фрагменте.

Код метода при создании:

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());


        mViewPager = (ViewPager) findViewById(R.id.pager_exp); 
        mViewPager.setAdapter(mSectionsPagerAdapter);


        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) 
                    {
                        actionBar.setSelectedNavigationItem(position);
                        actionBar.setTitle(getHomePageTitle(position)); 
                    }
                });


        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) 
        {
            // Create a tab with text corresponding to the page title defined by
            // the adapter. Also specify this Activity object, which implements
            // the TabListener interface, as the callback (listener) for when
            // this tab is selected.
            actionBar.addTab(actionBar.newTab()
                    .setIcon(getPagedrawable(i))
                    .setTabListener(this));

        }

// Код класса адаптера:

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) 
    {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {


    switch (position) 
    {
        case 0:
            Fragment1 f1 = new Fragment1(); 
            return f1;

        case 1:
            Fragment2 f2 = new Fragment2(); 
            return f2;

        case 2:
            Fragment3 f3 = new Fragment3();  
            return f3;

        case 3: 
            Fragment4 f4 = new Fragment4();
            return f4;


        case 4: 
            Fragment5 f5 = new Fragment5();
            return f5;

        }

        return null;

    }

    @Override
    public int getCount() {
        // Show 5 total pages.
        return 5;  
    } 


}

Код класса Фрагмент:

public class F1 extends Fragment 
{
@Override
public void onCreate(Bundle savedInstanceState)  
{
    super.onCreate(savedInstanceState);

}

 @SuppressLint("NewApi")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) 
{ 
    View view       = inflater.inflate(R.layout.f1,container, false);

     Toast.makeText(getActivity(), "F1", Toast.LENGTH_SHORT).show();
    return view;  
}   
}

person Community    schedule 20.02.2014    source источник


Ответы (4)


FragmentPagerAdapter сохраняет дополнительные фрагменты, помимо показанного, в возобновленном состоянии. Решение состоит в том, чтобы реализовать собственный OnPageChangeListener и создать новый метод для отображения фрагмента.

1) Создайте LifecycleManager интерфейс Интерфейс будет иметь два метода, и каждый ViewPager’s фрагмент будет его реализовывать. Эти методы заключаются в следующем:

public interface FragmentLifecycle {

    public void onPauseFragment();
    public void onResumeFragment();

}

2) Пусть каждый Fragment реализует оператор интерфейса Add iplements для каждого объявления класса:

public class FragmentBlue extends Fragment implements FragmentLifecycle
public class FragmentGreen extends Fragment implements FragmentLifecycle
public class FragmentPink extends Fragment implements FragmentLifecycle

3) Реализовать методы интерфейса в каждом фрагменте. Чтобы проверить, что он действительно работает так, как ожидалось, я просто запротоколирую вызов метода и покажу Toast:

@Override
public void onPauseFragment() {
    Log.i(TAG, "onPauseFragment()");
    Toast.makeText(getActivity(), "onPauseFragment():" + TAG, Toast.LENGTH_SHORT).show(); 
}

@Override
public void onResumeFragment() {
    Log.i(TAG, "onResumeFragment()");
    Toast.makeText(getActivity(), "onResumeFragment():" + TAG, Toast.LENGTH_SHORT).show(); 
}

4) Методы интерфейса вызова при изменении страницы ViewPager. Вы можете установить OnPageChangeListener на ViewPager и получать обратный вызов каждый раз, когда ViewPager показывает другую страницу:

pager.setOnPageChangeListener(pageChangeListener);

5) Реализуйте OnPageChangeListener для вызова ваших пользовательских методов жизненного цикла.

Слушатель знает новую позицию и может вызвать метод интерфейса для нового фрагмента с помощью PagerAdapter. Здесь я могу вызвать onResumeFragment() для нового фрагмента и onPauseFragment() для текущего.

Мне также нужно сохранить текущую позицию фрагмента (изначально текущая позиция равна 0), так как я не знаю, пролистывал ли пользователь слева направо или справа налево. Посмотрите, что я имею в виду в коде:

private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {

    int currentPosition = 0;

    @Override
    public void onPageSelected(int newPosition) {

        FragmentLifecycle fragmentToShow = (FragmentLifecycle)pageAdapter.getItem(newPosition);
        fragmentToShow.onResumeFragment();

        FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
        fragmentToHide.onPauseFragment();

        currentPosition = newPosition;
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) { }

    public void onPageScrollStateChanged(int arg0) { }
};

Я не писал код. Полное руководство здесь: http://looksok.wordpress.com/2013/11/02/viewpager-with-detailed-fragment-lifecycle-onresumefragment-include-source-code/

person LordRaydenMK    schedule 24.06.2014
comment
@SomeoneSomewhere необходимо возобновить соседние фрагменты, чтобы вы могли прокручивать их. - person LordRaydenMK; 05.08.2015
comment
Я понял - адаптер действительно важен: он должен создавать экземпляры всех фрагментов и сохранять на них ссылку. getItem() затем просто возвращает объект. К сожалению, у меня getItem() каждый раз создавал новый Fragment1, Fragment2 и т.д. Но, тем не менее, использование фрагментов внутри ViewPager невероятно сложно — до смешного. Текущая реализация действительно работает только для нескольких фрагментов, в противном случае использование кучи быстро увеличивается. - person Someone Somewhere; 05.08.2015
comment
@SomeoneSomewhere проверьте FragmentStatePagerAdapter. Эта версия пейджера более полезна, когда имеется большое количество страниц, и работает больше как представление списка. Когда страницы не видны пользователю, весь их фрагмент может быть уничтожен, сохранив только сохраненное состояние этого фрагмента. Это позволяет пейджеру удерживать гораздо меньше памяти, связанной с каждой посещенной страницей, по сравнению с FragmentPagerAdapter за счет потенциально больших накладных расходов при переключении между страницами. - person LordRaydenMK; 05.08.2015

Использовать это

viewPager.setOffscreenPageLimit(1); // the number of pages you want to load in background

а также ProgressDialogue.

person Sreejith SP    schedule 24.06.2014
comment
это не жизнеспособный ответ - person Someone Somewhere; 04.08.2015

ViewPager создает представления для фрагментов, смежных с вашей текущей страницей. Это также дает вам возможность загрузить любые данные, необходимые для соседних фрагментов. Если вы используете AsyncTasks для загрузки данных, использование этой функции улучшит взаимодействие с пользователем. Но если вам нужно событие, когда конкретная страница открывается вьюпейджером, решение LordRaydenMK сработает.

См. мой пост в следующем потоке для использования AsyncTasks в ViewPager:

AsyncTask запускается на каждой странице ViewPager

person Manas Chaudhari    schedule 28.06.2014

Привет. Вы можете попробовать, используя тег каждого фрагмента и метод вызова каждого фрагмента на странице изменена.

mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        actionBar.setSelectedNavigationItem(position);
                        actionBar.setTitle(getHomePageTitle(position));
                        Fragment f = getFragrmentManager().findFragmentByTag(
                                "" + position);
                        if (f != null)
                            f.refresh();
                    }
                });

и дальше

         @Override
        public Fragment getItem(int position) {
          Fragment f=null;

        switch (position) 
        {
            case 0:
                f = new Fragment1(); 
                break;

            case 1:
                 f = new Fragment2(); 
                 break;

            case 2:
                 f = new Fragment3();  
                 break;

            case 3: 
                f = new Fragment4();
                break;


            case 4: 
                 f = new Fragment5();
                break;

            }
             f.setTag(""+position);
            return f;

        }
person Ravi Kant    schedule 30.06.2014