Обновить фрагмент при перезагрузке

111

В приложении для Android я загружаю данные из базы данных во TableViewвнутренний файл Fragment. Но когда я перезагружаю, Fragmentон отображает предыдущие данные. Могу ли я повторно заполнить Fragmentтекущими данными вместо предыдущих?

Саманта Витхейдж
источник
покажите нам код, пожалуйста. Где вы загружаете свои данные, где вы начинаете свой фрагмент, где вы храните свои значения?
AS
Это должно решить вашу подробно описанную проблему: stackoverflow.com/questions/6503189/…
Benjamin W.
пожалуйста, предоставьте больше фрагмента информационного кода
nikvs
Попробуйте использовать Swipe-to-Refresh To Your App, см. Этот stackoverflow.com/questions/41469040/fragment-refresh/…
Имтиаз Мамун

Ответы:

207

Я думаю, вы хотите обновить содержимое фрагмента при обновлении db

Если да, отсоедините фрагмент и снова прикрепите его.

// Reload current fragment
Fragment frg = null;
frg = getSupportFragmentManager().findFragmentByTag("Your_Fragment_TAG");
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();

Your_Fragment_TAG - это имя, которое вы дали своему фрагменту при его создании.

Этот код предназначен для библиотеки поддержки.

Если вы не поддерживаете старые устройства, просто используйте getFragmentManager вместо getSupportFragmentManager.

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

Этот метод требует, чтобы фрагмент имел тег.
Если у вас его нет, то метод @ Hammer - это то, что вам нужно.

Phantômaxx
источник
3
Это дает следующую ошибку - java.lang.RuntimeException: Не удалось доставить результат ResultInfo {who = null, request = 2, result = 3, data = null} в действие {xont.virtusel.v4.controller / xont.virtusel.v4.controller .sale.InvocieBrandActivity}: java.lang.IllegalStateException: Невозможно выполнить это действие после onSaveInstanceState
Саманта Уитханейдж
1
@Elizabeth, убедитесь, что у вашего фрагмента правильно установлен тег
Phantômaxx
1
@Rotwang Спасибо за ваш ответ. Я просто использовал ярлык, а не длинный код, но это помогло проложить путь :)
Si8,
1
Это решение больше не работает в новой версии support-v4-library (25.1.0). Объяснение здесь: stackoverflow.com/questions/41270858/…
Брахим Буабуд
1
Предупреждение: этот трюк работает в Oreo, только если вы используете Support Fragments!
racs
147

Это обновит текущий фрагмент:

FragmentTransaction ft = getFragmentManager().beginTransaction();
if (Build.VERSION.SDK_INT >= 26) {
   ft.setReorderingAllowed(false);
}
ft.detach(this).attach(this).commit();
Mbengue Assane
источник
1
куда поставить этот код? внутри активности или самого фрагмента?
Нарендра Сингх
2
Вы помещаете его внутрь фрагмента, который нужно обновить.
Mbengue Assane
1
@SagarChavada где ты поместил код? Вы должны поместить его в одноразовое событие, например, когда данные обновляются.
Mbengue Assane
5
Рекурсия, рекурсия, бесконечные вызовы
zulkarnain shah
2
Использование этого создает внутри onResume во фрагменте создается цикл, как этого избежать?
Soul
32

Если у вас нет тега фрагмента, мне подходит следующий код.

Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
if (currentFragment instanceof "NAME OF YOUR FRAGMENT CLASS") {
 FragmentTransaction fragTransaction =   (getActivity()).getFragmentManager().beginTransaction();
 fragTransaction.detach(currentFragment);
 fragTransaction.attach(currentFragment);
 fragTransaction.commit();}
}
молоток
источник
1
какой будет идентификатор фрагмента, я нигде не объявлял идентификатор фрагмента. Как и где это заявить?
Нарендра Сингх
Не могу использовать getActivity()в моей деятельности. Стоит ли использовать Activity.this...?
Si8
@NarendraJi - это только идентификатор FrameLayout, в который вы помещаете свои фрагменты в контейнер.
Локеш
Удалите лишнюю скобу. Это доставило мне много хлопот.
Абхишек
9

вы можете обновить свой фрагмент, когда он виден пользователю, просто добавьте этот код в свой фрагмент, это обновит ваш фрагмент, когда он станет видимым.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // Refresh your fragment here          
  getFragmentManager().beginTransaction().detach(this).attach(this).commit();
        Log.i("IsRefresh", "Yes");
    }
}
Кошик Хамбхадия
источник
так медленно, что перезагрузка занимает 3 секунды
Омар Бошра
Это , кажется, работает хорошо с ViewPager адаптером
DragonFire
2
setUserVisibleHint устарел
Сай Адитья
У меня сработало, спасибо за решение.
hetsgandhi
7

Чтобы обновить фрагмент, принятый ответ не будет работать в версии Nougat и выше. Чтобы он работал на всех ОС, вы можете сделать следующее.

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        fragmentManager.beginTransaction().detach(this).commitNow();
        fragmentManager.beginTransaction().attach(this).commitNow();
    } else {
        fragmentManager.beginTransaction().detach(this).attach(this).commit();
    }
Сачин Джагтап
источник
5

Вы не можете перезагрузить фрагмент, пока он прикреплен к Activity, где возникает Fragment Already Addedисключение.

Таким образом, фрагмент необходимо сначала отсоединить от его активности, а затем присоединить. Все это можно сделать с помощью свободного API в одной строке:

getFragmentManager().beginTransaction().detach(this).attach(this).commit();

Обновление: чтобы включить изменения, внесенные в API 26 и выше:

FragmentTransaction transaction = mActivity.getFragmentManager()
                        .beginTransaction();
                if (Build.VERSION.SDK_INT >= 26) {
                    transaction.setReorderingAllowed(false);
                }
                transaction.detach(this).attach
                        (this).commit();

Дополнительное описание обновления см. На странице https://stackoverflow.com/a/51327440/4514796.

Али Нем
источник
2
Пожалуйста, дайте свой ответ с четкими описаниями. Не пишите код, дайте объяснение кода, которым вы поделились, чтобы другие также могли понять, и это будет полезно. Я прошу вас прочитать раздел часто задаваемых вопросов, чтобы эффективно использовать Stack Overflow.
Санкар Ганеш
3
   MyFragment fragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
        getSupportFragmentManager().beginTransaction().detach(fragment).attach(fragment).commit();

это будет работать, только если вы используете FragmentManagerдля инициализации фрагмента. Если у вас есть это как <fragment ... />в XML, он не будет вызывать onCreateViewснова. Потратил свои 30 минут, чтобы понять это.

Иршу
источник
1

Вот что я сделал, и это сработало для меня, я использую firebase, и когда пользователь входит в систему, я хотел сначала обновить текущий фрагмент, вам нужно будет запросить контекст из активности, потому что у фрагмента нет способа получить контекст, если вы не установите его из Activity или context здесь это код, который я использовал и работал на языке котлин, я думаю, вы могли бы использовать то же самое в классе java

   override fun setUserVisibleHint(isVisibleToUser: Boolean) {
    super.setUserVisibleHint(isVisibleToUser)
    val context = requireActivity()
    if (auth.currentUser != null) {
        if (isVisibleToUser){
            context.supportFragmentManager.beginTransaction().detach(this).attach(this).commit()
        }
    }

}
HardiBSalih
источник
0

Используйте ContentProviderи загрузите данные с помощью CursorLoader. С этой архитектурой ваши данные будут автоматически перезагружаться при изменении базы данных. Используйте сторонние фреймворки для себя ContentProvider- вы действительно не хотите реализовывать это самостоятельно ...

artkoenig
источник
0

У меня была такая же проблема, но ничего из вышеперечисленного не помогло мне. либо возникла проблема с обратным стеком (после загрузки, когда пользователь нажал обратно, он снова перешел к тому же фрагменту), либо он не вызвалonCreaetView

наконец я сделал это:

public void transactFragment(Fragment fragment, boolean reload) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    if (reload) {
        getSupportFragmentManager().popBackStack();
    }
    transaction.replace(R.id.main_activity_frame_layout, fragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

Хороший момент - вам не нужен ни тег, ни идентификатор фрагмента. если вы хотите перезагрузить

Имад
источник
0

Используйте метод onResume ... как для активности фрагмента, так и для активности, содержащей фрагмент.

Мванги Гитуати
источник
0
getActivity().getSupportFragmentManager().beginTransaction().replace(GeneralInfo.this.getId(), new GeneralInfo()).commit();

GeneralInfo это мой класс фрагмента GeneralInfo.java

Я поместил это как метод в класс фрагмента:

public void Reload(){
    getActivity().getSupportFragmentManager().beginTransaction().replace(LogActivity.this.getId(), new LogActivity()).commit();
}
Брайан Стивен Мартинес Ванегас
источник
0

Например, с TabLayout: просто реализуйте OnTabSelectedListener. Чтобы перезагрузить страницу, вы можете использовать реализацию SwipeRefreshLayout.OnRefreshListener, т.е.public class YourFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

метод onRefresh () будет @Override из интерфейса, т.е.

@Override
public void onRefresh() {
 loadData();
}

Вот макет:

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tablayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimaryLighter"
    app:tabGravity="fill"
    app:tabIndicatorColor="@color/white"
    app:tabMode="fixed"
    app:tabSelectedTextColor="@color/colorTextPrimary"
    app:tabTextColor="@color/colorTextDisable" />

Код в вашей деятельности

TabLayout tabLayout = (TabLayout) findViewById (R.id.tablayout); tabLayout.setupWithViewPager (viewPager);

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            if (tab.getPosition() == 0) {
                yourFragment1.onRefresh();
            } else if (tab.getPosition() == 1) {
                yourFragment2.onRefresh();
            }
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
Парень JavaEE
источник
-2
protected void onResume() {
        super.onResume();
        viewPagerAdapter.notifyDataSetChanged();
    }

Напишите viewpagerAdapter.notifyDataSetChanged (); в onResume () в MainActivity. Удачи :)

Хэнди Ким
источник
-2

Самый простой способ

сделать общедоступный статический метод, содержащий viewpager.setAdapter

сделать адаптер и просмотрщик статическими

public static void refreshFragments(){
        viewPager.setAdapter(adapter);
    }

звонить куда угодно, любую активность, любой фрагмент.

MainActivity.refreshFragments();
Райан Кристопер Лукасан
источник