Фрагменты ViewPager со временем уничтожаются?
Я использую пакет Android support.v4
для создания ViewPager, содержащего несколько Fragment
s.
Я пытаюсь скрыть Представления, когда пользователь меняет страницу. Итак, я выполнил OnPageChangeListener
для прослушивания моего адаптера и вызвал метод update()
в моем Fragment
, когда происходит смена страницы. Но я получаю 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);
Ответы
Ответ 1
Добавьте, когда вы инициализируете свой ViewPager
,
mPager.setOffscreenPageLimit(NUM_ITEMS-1);
В вашем случае это приведет к тому, что количество экранных страниц станет равным 1 (т.е. будет удерживать дополнительную экранную страницу в памяти, когда другая страница находится в фокусе). Это заставит ваш ViewPager
сохранить все Fragment
, даже если они не находятся в фокусе.
Ответ 2
Я просмотрел ваш код, и я думаю, проблема в том, что в onPageScrolled
вы вызываете getItem
. Эта реализация (которая на самом деле похожа на большинство ее реализаций в Интернете) каждый раз возвращает новый экземпляр. Однако большинство примеров, которые я видел, не называют getItem
, поэтому это обычно хорошо.
В вашем случае я лениво создаю фрагмент в getItem
: если он не существует для этой позиции, затем создайте его, а затем вставьте в него в ArrayList
или какую-либо другую коллекцию, но если он уже существует, просто верните его из этой коллекции.
В противном случае вы создаете экземпляр фрагмента A, а затем прокрутите его до другого экземпляра экземпляра B. Попробуйте сообщить фрагменту экземпляра A, чтобы очистить некоторые виды, но вы завершаете рассказ о новом экземпляре фрагмента C для этого. У него еще не было возможности настроить свои собственные представления, поэтому вы получаете нулевой указатель на диаграммы.