Вызов функции «Стоп» в закладках

У меня есть 3 вкладки swipes (A, B, C) в моем андроиде. Когда приходит к вкладкам c, у меня есть функция RetrieveData() , используемая для извлечения данных из MySQL и загрузки в listView .

Предположим, что в MySQL у меня есть только одна строка данных, когда доходит до c, данные будут загружены в listView (только один список). Когда я перейду к Tab A и снова перейду к C, список станет 2 сейчас. Есть ли способ, который я могу сделать, чтобы RetrieveData() вызывал только один раз? Благодарю.

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View edit_details = inflater.inflate(R.layout.edit_work_details, container, false); // EditDetails = new ArrayList<HashMap<String, String>>(); listViewUpdate = (ListView) edit_details.findViewById(R.id.listViewEdit); totalHours=(TextView)edit_details.findViewById(R.id.hour); setHasOptionsMenu(true); Bundle bundle = this.getArguments(); if (getArguments() != null) { ID = bundle.getString("ID"); RetrieveData(ID); // retrieve data from MySQL } Toast.makeText(getActivity(), "Details" + ID, Toast.LENGTH_LONG).show(); } 

TabAdapter

 public class TabsFragmentPagerAdapter extends FragmentPagerAdapter { public TabsFragmentPagerAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } @Override public Fragment getItem(int index) { // TODO Auto-generated method stub if(index == 0) { Fragment fragment=new A(); Bundle bundle = new Bundle(); bundle.putString("ID", Edit.ID); fragment.setArguments(bundle); return fragment; } if(index == 1) { Fragment fragment = new B(); Bundle bundle = new Bundle(); bundle.putString("ID", Edit.ID); fragment.setArguments(bundle); return fragment; } if(index == 2) { Fragment fragment = new C(); Bundle bundle = new Bundle(); bundle.putString("ID", Edit.ID); fragment.setArguments(bundle); return fragment; } return null; } @Override public int getCount() { // TODO Auto-generated method stub return 3; } } 

Код ViewPager

 public class ActivityB extends ActionBarActivity implements ActionBar.TabListener { private ViewPager viewPager; private ActionBar actionBar; private TabsFragmentPagerAdapter tabsAdapter; private String[] item = new String[]{"Information","Work Force","Work Details"}; private String id; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_b); // id=getIntent().getExtras().getString("ID"); viewPager = (ViewPager) findViewById(R.id.viewPager); tabsAdapter = new TabsFragmentPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(tabsAdapter); actionBar = getSupportActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); for(int i=0; i<4; i++){ actionBar.addTab(actionBar.newTab().setText(item[i]).setTabListener(this)); } viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int arg) { // TODO Auto-generated method stub actionBar.setSelectedNavigationItem(arg); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } }); } @Override public void onTabReselected(ActionBar.Tab arg0, FragmentTransaction arg1) { // TODO Auto-generated method stub } @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction arg1) { // TODO Auto-generated method stub viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(ActionBar.Tab arg0, FragmentTransaction arg1) { // TODO Auto-generated method stub } } 

Это моя вкладка c

Введите описание изображения здесь

После повторного прокрутки до A и C

Введите описание изображения здесь

Похоже, он снова вызывает RetrieveData .

Solutions Collecting From Web of "Вызов функции «Стоп» в закладках"

Вы должны использовать setOffscreenPageLimit ViewPager . Он установит, сколько страниц пейджера вы хотите загрузить вначале.

Значение Bydefault для setOffScreeenPageLimit равно 1, поэтому он загружает текущую страницу и следующую страницу. В вашем случае он будет загружать A и B , когда вы перейдете на C из B он уничтожит экземпляр A

Попробуйте использовать

 `pager.setOffscreenPageLimit(2)` 

Он будет загружать текущую страницу и еще 2 страницы, так что A, B и C будут загружены один раз.

РЕДАКТИРОВАТЬ

Задайте количество страниц, которые должны быть сохранены в обе стороны текущей страницы в иерархии представлений в состоянии ожидания. Страницы, выходящие за этот предел, будут воссозданы с адаптера, если это необходимо.

Это предлагается как оптимизация. Если вы заранее знаете количество страниц, которые вам понадобятся для поддержки или имеют механизмы ленивой загрузки на ваших страницах, настройка этой настройки может иметь преимущества в воспринимаемой гладкости анимации и взаимодействия пейджинга. Если у вас есть небольшое количество страниц (3-4), которые вы можете сохранить активными одновременно, меньше времени будет потрачено на макет для вновь созданных подтипов просмотра в качестве страниц пользователя взад и вперед.

Источник

Это явно означает, что вы можете установить количество страниц, которые хотите загрузить на начальном уровне, если вы хотите сначала загрузить 5 страниц, установите его значение 4.

Теперь, если вы перейдете с любой страницы на 5 страниц, onCreateView() Fragment не будет вызываться, так как он уже загружен на начальном этапе.

Если вы извлекаете из БД каждый раз, когда вы садитесь на C , вам нужно очистить список перед рукой, либо в методе onResume при вводе фрагмента, либо в методе onPause когда вы покидаете фрагмент.

Это означает, что, например, очистите ваш ArrayList и убедитесь, что он не является static , иначе это означает, что вам нужно очистить ListView с помощью listView.setAdapter(null); , Затем не забудьте использовать notififyDatasetChanged() на адаптере.

Поскольку вы не вставили свой код RetrieveData (), я предполагаю, что вы читаете данные в ArrayList <> или перебираете курсор. Кроме того, нет других мест, где вы вызываете этот метод, кроме onCreateVie (). Некоторые из возможных решений могут быть следующими:

  1. Если вы явно устанавливаете viewPager.setOffscreenPageLimit (x), где x> 1, удалите этот код. По умолчанию это значение равно 1 и просмотр пейджера каждый раз вызывает createView.
  2. Поскольку вы используете FragmentPagerAdapter, как только вы правильно загрузили фрагмент C, его не следует создавать снова, поскольку он должен присутствовать в памяти, и ViewPager будет использовать это. Проверьте, будет ли каждый раз вызывать onCreateView () для фрагмента C ,
  3. Убедитесь, что каждый раз, когда вы возвращаете данные в список, вы не добавляете в список, а не очищаете список, а затем добавляете его.

Пожалуйста, попробуйте выше.

Многие ответы предлагают setOffscreenPageLimit, но я бы не рекомендовал его по двум причинам.

1) Ресурсы фрагмента в viewpager не будут собирать мусор, даже если они не отображаются. Это вызовет проблемы с памятью, если у вас есть объекты, содержащие память, например растровые изображения.

2) Этот подход будет недостаточным, если приложение перейдет на задний план и снова появится на переднем плане.

Я предлагаю сохранять ваши данные в onSaveInstanceState в каждом фрагменте в ViewPager и проверять, есть ли данные, сохраненные в onCreate. Если есть данные, покажите это. В противном случае запрос данных.

Я столкнулся с аналогичной проблемой когда-нибудь, вопрос был с моим кодом, при получении даты из БД, я заполнял список, и всякий раз, когда страница обновляется, он не будет создавать новый список, он непосредственно добавлял те же данные в список, что Уже содержит данные и показывает две строки с одинаковой записью. Чтобы решить эту проблему, я очистил свой список перед заполнением данных.

Это можно предотвратить, установив параметр ViewPager 2 в экземпляр ViewPager . Вот документы –

 /** * Set the number of pages that should be retained to either side of the * current page in the view hierarchy in an idle state. Pages beyond this * limit will be recreated from the adapter when needed. * * <p>This is offered as an optimization. If you know in advance the number * of pages you will need to support or have lazy-loading mechanisms in place * on your pages, tweaking this setting can have benefits in perceived smoothness * of paging animations and interaction. If you have a small number of pages (3-4) * that you can keep active all at once, less time will be spent in layout for * newly created view subtrees as the user pages back and forth.</p> * * <p>You should keep this limit low, especially if your pages have complex layouts. * This setting defaults to 1.</p> * * @param limit How many pages will be kept offscreen in an idle state. */ public void setOffscreenPageLimit(int limit) { if (limit < DEFAULT_OFFSCREEN_PAGES) { Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + DEFAULT_OFFSCREEN_PAGES); limit = DEFAULT_OFFSCREEN_PAGES; } if (limit != mOffscreenPageLimit) { mOffscreenPageLimit = limit; populate(); } }