#java #android #android-fragments
#java #Android #android-фрагменты
Вопрос:
У меня эта проблема с моим Android Fragment
. Происходит то, что у меня есть несколько Fragment
s в моем TabLayout
. Я создаю их без проблем, но я сталкиваюсь с проблемой, когда при первом создании экземпляра Fragment
создается фрагмент, и данные, похоже, изначально загружены правильно. Однако после того, как все данные загружены изначально, выполняется второй вызов для создания экземпляра, Fragment
потому что Fragment getItem(int position)
по какой-то причине метод вызывается еще раз. Однако, поскольку я инициализирую данные только в первый раз (в моем фрагменте есть static
переменная, которую я создал, которая инициализирует данные для меня), static
переменная уже будет знать, что данные уже загружены правильно и что она не должна загружать данные снова. В результате мой экран загрузки, похоже, отображается непрерывно, потому что данные во второй раз не могут быть извлечены. Есть ли какой-либо способ обойти это? Либо фрагмент создается только один раз, либо загружаются данные только во второй и последний раз, когда Fragment
создается? Вот мой код:
private void setupTabLayout() {
View layout = findViewById(R.id.activity_main);
if (layout != null) {
tabLayout = (TabLayout) layout.findViewById(R.id.tab_layout);
}
tabLayout.addTab(tabLayout.newTab().setText("First Fragment"));
tabLayout.addTab(tabLayout.newTab().setText("Second Fragment"));
tabLayout.addTab(tabLayout.newTab().setText("Third Fragment"));
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
if(viewPager != null) {
viewPager.setOffscreenPageLimit(3);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
PagerAdapter.java
public class PagerAdapter extends FragmentStatePagerAdapter{
int numTabs;
public PagerAdapter(FragmentManager fm, int numTabs) {
super(fm);
this.numTabs = numTabs;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
//Here, the PublicTabFragment is instantiated twice,
//causing the onResume and onCreate methods of my PublicTabFragment()
//to be called twice.
PublicTabFragment tab1 = new PublicTabFragment();
return tab1;
case 1:
FollowersTabFragment tab2 = new FollowersTabFragment();
return tab2;
case 2:
ProfileTabFragment tab3 = new ProfileTabFragment();
return tab3;
default:
return null;
}
}
@Override
public int getCount() {
return numTabs;
}
PublicTabFragment:
private View fragmentView;
private View progressOverlay;
//Declared static so I don't have to call getPublicPostsFromDatabase twice
private static LocationService locationService;
private static Location currentLocation;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (fragmentView == null) {
fragmentView = inflater.inflate(R.layout.posts_tab, container, false);
}
return fragmentView;
}
@Override
public void onResume() {
super.onResume();
setupLocation();
}
private void setupLocation() {
Context context = getContext();
//Checked once staticly so I don't have to call getPublicPostsFromDatabase twice
if(locationService == null) {
locationService = new LocationService(context, new LocationUpdateListener() {
@Override
public void canReceiveLocationUpdates() {
}
@Override
public void cannotReceiveLocationUpdates() {
//well we know we cant receive updates so we have to create a settings request
}
//update location to our servers for tracking purpose
@Override
public void updateLocation(Location location) {
if (location != null) {
currentLocation = location;
progressOverlay = fragmentView.findViewById(R.id.progress_overlay);
progressOverlay.setVisibility(View.VISIBLE);
swipeContainer = (SwipeRefreshLayout) fragmentView.findViewById(R.id.swipeContainer);
swipeContainer.setColorSchemeResources(R.color.colorPrimary);
databaseQuery.getPublicPostsFromDatabase(currentLocation, progressOverlay, fragmentView, getContext(), R.id.public_posts_feed);
}
}
@Override
public void updateLocationName(String localityName, Location location) {
locationService.stopLocationUpdates();
}
});
locationService.startUpdates();
}
}
РЕДАКТИРОВАТЬ: я попытался установить для locationService
переменной значение НЕ static, и вызов getPublicPostsFromDatabase работает нормально во второй раз, когда создается экземпляр фрагмента, но затем проблема заключается в том, что getPublicPostsFromDatabase
метод вызывается дважды. Даже если я установлю, что a static boolean variable
находится true
внутри getPublicPostsFromDatabase
и вызывается getPublicPostsFromDatabase
только тогда, когда static boolean variable
есть false
, Fragment
экземпляр создается во второй раз только после getPublicPostsFromDatabase
завершения, которое затем будет getPublicPostsFromDatabase
вызвано снова.
Ответ №1:
Вы пробовали с логическим значением?
private Boolean mLoad = false;
и когда они загружаются, установите для него значение true, а для загрузки установите это условие
if (!mLoad) {
...
mLoad = true;
}
Комментарии:
1. Я пробовал использовать логическое значение, но проблема, похоже, в том, что
getPublicPostsFromDatabase
оно завершается до создания экземпляраFragment
во второй раз. В результатеgetPublicPostsFromDatabase
вызывается снова, что совсем не то, чего я хотел бы в идеале. Есть еще какие-нибудь предложения?2. @Ritesh не могли бы вы пояснить, что вы подразумеваете под EventBus для управления загрузкой данных?
3. шина событий — это зависимость, в которой вы можете запускать событие и перехватывать событие в любом месте приложения, например: — andreas-schrade.de/2015/11/28 /…
Ответ №2:
Установите setOffscreenPageLimit, чтобы не загружать данные фрагмента again.so попробуйте эту строку ниже:
viewPager.setOffscreenPageLimit(yourNooftab);
Комментарии:
1. Я не думаю, что это сработает. Это потому, что моя первая вкладка будет загружена дважды, несмотря ни на что, даже если я установлю ограничение на страницу вне экрана равным 0.