Odśwież fragment przy przeładowaniu


110

W aplikacji na Androida ładuję dane z bazy danych do pliku TableViewwewnętrznego Fragment. Ale kiedy przeładowuję Fragment, wyświetla poprzednie dane. Czy mogę ponownie wypełnić Fragmentbieżące dane zamiast poprzednich danych?


pokaż nam kod. Gdzie ładujesz swoje dane, gdzie zaczynasz swój fragment, gdzie przechowujesz swoje wartości?
WG

To powinno rozwiązać twój problematyczny opisywany problem: stackoverflow.com/questions/6503189/ ...
Benjamin W.

proszę podać więcej informacji - fragment kodu
nikvs

Spróbuj użyć funkcji Swipe-to-Refresh do swojej aplikacji, zobacz ten stackoverflow.com/questions/41469040/fragment-refresh/…
Imtiaz Mamun

Odpowiedzi:


207

Myślę, że chcesz odświeżyć zawartość fragmentu po aktualizacji db

Jeśli tak, odłącz fragment i ponownie go przymocuj

// 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 to nazwa, którą nadałeś fragmentowi podczas jego tworzenia

Ten kod jest przeznaczony dla biblioteki wsparcia.

Jeśli nie obsługujesz starszych urządzeń, po prostu użyj getFragmentManager zamiast getSupportFragmentManager

[EDYTOWAĆ]

Ta metoda wymaga, aby fragment miał tag.
Jeśli go nie masz, to metoda @ Hammera jest tym, czego potrzebujesz.


3
Daje to następujący błąd - java.lang.RuntimeException: Niepowodzenie dostarczania wyniku ResultInfo {who = null, request = 2, result = 3, data = null} do działania {xont.virtusel.v4.controller / xont.virtusel.v4.controller .sale.InvocieBrandActivity}: java.lang.IllegalStateException: Nie można wykonać tej czynności po onSaveInstanceState
Samantha Withanage

1
@Elizabeth, upewnij się, że Twój Fragment ma poprawnie ustawiony tag
Phantômaxx

1
@Rotwang Dzięki za twoją odpowiedź Po prostu poszedłem na skróty, zamiast robić długi kod, ale to pomogło utorować drogę :)
Si8

1
To rozwiązanie nie działa już w nowej wersji support-v4-library (25.1.0). Wyjaśnienie tutaj: stackoverflow.com/questions/41270858/…
Brahim Bouaboud,

1
Ostrzeżenie: ta sztuczka działa na Oreo tylko wtedy, gdy używasz fragmentów wsparcia!
wyścigi

146

To odświeży aktualny fragment:

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

1
gdzie umieścić ten kod? aktywność wewnętrzna czy sam fragment?
Narendra Singh

2
Umieszczasz go w fragmencie, który wymaga odświeżenia.
Mbengue Assane

1
@SagarChavada Gdzie umieściłeś kod? Musisz umieścić to w jednorazowym zdarzeniu, takim jak odświeżanie danych.
Mbengue Assane,

5
Rekursja, rekurencja, niekończące się rozmowy
zulkarnain shah

2
Użycie tego tworzy w onResume we fragmencie tworzy pętlę, jak tego uniknąć?
Soul

32

W przypadku, gdy nie masz tagu fragmentu, poniższy kod działa dobrze dla mnie.

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
jaki będzie identyfikator fragmentu, nigdzie nie zadeklarowałem identyfikatora fragmentu. Jak i gdzie to zgłosić?
Narendra Singh

Nie można użyć getActivity()w mojej aktywności. Powinienem użyć Activity.this...?
Si8

@NarendraJi to tylko identyfikator FrameLayout, w którym umieszczasz swoje fragmenty w kontenerze.
Lokesh

Usuń ten dodatkowy wspornik. Sprawiło mi to wiele kłopotów.
Abhishek

9

możesz odświeżyć swój fragment, gdy jest widoczny dla użytkownika, po prostu dodaj ten kod do swojego fragmentu, co spowoduje odświeżenie fragmentu, gdy będzie widoczny.

@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");
    }
}

tak wolno, że przeładowanie trwa 3 sekundy
Omar Boshra

Wygląda na to, że działa dobrze z adapterem przeglądarki
DragonFire

2
setUserVisibleHint jest przestarzały
Sai Aditya

Pracował dla mnie, dzięki za rozwiązanie.
hetsgandhi

7

Aby odświeżyć fragment zaakceptowana odpowiedź nie będzie działać na wersji Nougat i nowszych. Aby to działało na wszystkich systemach operacyjnych, możesz wykonać następujące czynności.

    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

Nie możesz ponownie załadować fragmentu, gdy jest on dołączony do działania, w którym otrzymujesz „Fragment Already Added wyjątek ”.

Tak więc fragment należy najpierw oderwać od jego aktywności, a następnie dołączyć. Wszystko można zrobić za pomocą płynnego interfejsu API w jednej linii:

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

Aktualizacja: ma to na celu uwzględnienie zmian wprowadzonych w API 26 i nowszych:

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

Więcej informacji na temat aktualizacji można znaleźć na stronie https://stackoverflow.com/a/51327440/4514796


2
Prosimy o podanie odpowiedzi wraz z jasnymi opisami. Nie pisz kodu, podaj wyjaśnienie kodu, który udostępniłeś, aby inni też mogli go zrozumieć i będzie to pomocne. Proszę o przeczytanie sekcji FAQ, aby efektywnie używać Stack Overflow.
Sankar Ganesh

3
   MyFragment fragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
        getSupportFragmentManager().beginTransaction().detach(fragment).attach(fragment).commit();

zadziała to tylko wtedy, gdy użyjesz FragmentManagerdo zainicjowania fragmentu. Jeśli masz go jako <fragment ... />plik XML, nie wywoła tego onCreateViewponownie. Zmarnowałem 30 minut, żeby to rozgryźć.


1

Tutaj to, co zrobiłem i zadziałało dla mnie, używam firebase i kiedy użytkownik jest zalogowany Chciałem najpierw odświeżyć bieżący fragment, będziesz musiał zażądać kontekstu z aktywności, ponieważ fragment nie ma sposobu na uzyskanie kontekstu, chyba że ustawisz go tutaj z Aktywności lub kontekstu to kod, którego użyłem i pracowałem w języku kotlin, myślę, że możesz użyć tego samego w klasie 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()
        }
    }

}

0

Użyj a ContentProvideri załaduj dane za pomocą „CursorLoader”. Dzięki tej architekturze Twoje dane będą automatycznie ładowane ponownie po zmianach w bazie danych. Użyj ram osób trzecich dla twojego ContentProvider- tak naprawdę nie chcą wprowadzić go przez siebie ...


0

Miałem ten sam problem, ale żaden z powyższych nie działał dla mojego. albo wystąpił problem z backstackiem (po załadowaniu, gdy użytkownik nacisnąłby to ponownie, mógł przejść do tego samego fragmentu) lub nie wywołałonCreaetView

w końcu zrobiłem to:

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();
}

dobra uwaga jest taka, że ​​nie potrzebujesz tagu ani identyfikatora fragmentu. jeśli chcesz przeładować


0

Skorzystaj z metody onResume ... zarówno na aktywności fragmentu, jak i na aktywności trzymającej fragment.


0
getActivity().getSupportFragmentManager().beginTransaction().replace(GeneralInfo.this.getId(), new GeneralInfo()).commit();

GeneralInfo to moja klasa Fragment GeneralInfo.java

Umieściłem to jako metodę w klasie fragmentu:

public void Reload(){
    getActivity().getSupportFragmentManager().beginTransaction().replace(LogActivity.this.getId(), new LogActivity()).commit();
}

0

Na przykład z TabLayout: po prostu zaimplementuj OnTabSelectedListener. Aby ponownie załadować stronę, możesz użyć implementacji SwipeRefreshLayout.OnRefreshListener iepublic class YourFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

metoda onRefresh () będzie @Override z interfejsu, tj .:

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

Oto układ:

<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" />

Koduj w swojej działalności

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) {

        }
    });

-2
protected void onResume() {
        super.onResume();
        viewPagerAdapter.notifyDataSetChanged();
    }

Napisz viewpagerAdapter.notifyDataSetChanged (); w onResume () w MainActivity. Powodzenia :)


-2

Najprostszy sposób

stwórz publiczną metodę statyczną zawierającą viewpager.setAdapter

uczynić adapter i przeglądarkę statyczną

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

zadzwoń wszędzie, każdą czynność, dowolny fragment.

MainActivity.refreshFragments();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.