ViewPager Фрагменты разрушаются со временем? - PullRequest
17 голосов
/ 25 марта 2012

Я использую пакет Android support.v4 для разработки ViewPager, содержащего несколько Fragment s.

Я пытаюсь скрыть виды, когда пользователь меняет страницу.Итак, я реализовал OnPageChangeListener для прослушивания моего адаптера и вызывал метод update() в моих Fragment s, когда происходит изменение страницы.Но я получаю NullPointerException, и я не могу понять, почему.

Вот код:

public class MyActivity extends FragmentActivity implements
        OnPageChangeListener {

    private static final int NUM_ITEMS = 2;
    private ViewPager mPager;
    private static SpaceAdapter mAdapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_pager);

        mAdapter = new SpaceAdapter(getSupportFragmentManager());
        mPager = (ViewPager) findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);

        mPager.setOnPageChangeListener(this);
}

    public static class SpaceAdapter extends FragmentPagerAdapter {

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

        @Override
        public int getCount() {
            return NUM_ITEMS;
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
            case 0:
            return new MyFragment();
            case 1:
            return new MyFragment();
            default:
            return new MyFragment();
            }
        }
    }

    @Override
    public void onPageScrollStateChanged(int arg0) {
        Log.i("pagination", "scroll state changed: " + arg0);
}

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
        // Log.i("pagination", "page scroll: " + arg0 + " with: " + arg1 + ", " + arg2);
        if (mAdapter.getItem(arg0) instanceof IUpdateOnPage) {
            ((IUpdateOnPage) mAdapter.getItem(arg0)).updateOnPage();
        }
    }

    @Override
    public void onPageSelected(int arg0) {
        Log.i("pagination", "page selected: " + arg0);
    }
}

и

public class MyFragment extends Fragment implements
        SurfaceHolder.Callback, IUpdateOnPage {

    private SurfaceView charts;

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.crew, null);
        bindViews(v);
        return v;
    }

    private void bindViews(View v) {
        charts = (SurfaceView) v.findViewById(R.id.civ_charts);

        charts.getHolder().addCallback(this);
        Log.i("wtf", "huh " + String.valueOf(charts == null)); // logs false
    }

    @Override
    public void updateOnPage() {
        if (charts != null) {
            Log.i("crew surface", "hidden");
            charts.setVisibility(View.GONE);
        } else {
            Log.i("crew surface", "charts is null");  //THIS HERE gets logged
        }
    }
}

wКогда я копирую/ вставил Я удалил SurfaceHolder.Callback методы, но они есть.Метод bindViews(v) регистрирует, если charts == null, и это всегда возвращает false.Когда я выполняю страницу, вызывается updateOnPage, а charts == null возвращает true.Почему это происходит и как мне обойти это?

и это строка 108:

charts.setVisibility(View.GONE);

Ответы [ 2 ]

36 голосов
/ 25 марта 2012

Добавьте следующее, когда вы инициализируете свои ViewPager,

mPager.setOffscreenPageLimit(NUM_ITEMS-1);

. В вашем случае это установит количество страниц за пределами экрана равным 1 (то есть сохранит дополнительную страницу за пределами экрана).в памяти, когда другая страница находится в фокусе).Это заставит ваши ViewPager удерживать все Fragment с, даже когда они не в фокусе.

4 голосов
/ 25 марта 2012

Я проверил ваш код и думаю, что проблема в onPageScrolled, вы звоните getItem.Эта реализация (которая на самом деле похожа на большинство реализаций в Интернете) каждый раз возвращает новый экземпляр.Тем не менее, большинство примеров, которые я видел, не вызывают getItem, так что обычно все в порядке.

В вашем случае я бы с ленивостью создал Фрагмент в getItem: если он не существуетдля этой позиции затем создайте ее, а затем повесьте на нее в ArrayList или какой-либо другой коллекции, но если она уже существует, просто верните ее из этой коллекции.

В противном случае вы создаете экземпляр фрагмента A, затем перейдите к другому экземпляру фрагмента B. Вы пытаетесь сказать экземпляру фрагмента A, чтобы очистить некоторые представления, но в итоге вы говорите новому экземпляру фрагмента C сделать это.У него еще не было возможности настроить свои собственные представления, поэтому вы получаете нулевой указатель на графики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...