Оновити фрагмент при перезавантаженні


110

У додатку для Android я завантажую дані з Db TableViewвсередину a Fragment. Але коли я перезавантажую, Fragmentвін відображає попередні дані. Чи можу я переповнити Fragmentпоточні дані замість попередніх даних?


покажіть нам будь-який код, будь ласка. Де ви завантажуєте свої дані, де починаєте свій фрагмент, де зберігаєте свої цінності?
AS

Це повинно вирішити вашу porly описаної проблеми: stackoverflow.com/questions/6503189 / ...
Benjamin W.

будь ласка, надайте додатковий фрагмент інфо-коду
nikvs

Спробуйте скористатися функцією "Прокрутити оновлення до свого додатка", перегляньте це stackoverflow.com/questions/41469040/fragment-refresh/…
Imtiaz Mamun

Відповіді:


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

[EDIT]

Цей метод вимагає, щоб фрагмент мав тег.
Якщо у вас цього немає, тоді вам потрібен метод @ Hammer.


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
Samantha Withanage

1
@Elizabeth переконайтеся, що у вашому фрагменті правильно встановлений тег
Phantômaxx

1
@Rotwang Дякую за вашу відповідь, я просто взяв ярлик, а не робити довгий код, але це допомогло прокласти шлях :)
Si8,

1
У новій версії support-v4-library (25.1.0) це рішення більше не працює. Розшифровка тут: stackoverflow.com/questions/41270858 / ...
Брахім Bouaboud

1
Попередження: цей трюк працює на Oreo, лише якщо ви використовуєте фрагменти підтримки!
racs

146

Це оновить поточний фрагмент:

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

1
куди поставити цей код? всередині діяльності чи сам фрагмент?
Нарендра Сінгх

2
Ви помістите його всередину фрагмента, який потрібно оновити.
Mbengue Assane

1
@SagarChavada, куди ти поставив код? Ви повинні помістити його в разові події, наприклад, коли дані оновлюються.
Mbengue Assane

5
Рекурсія, рекурсія, нескінченні дзвінки
zulkarnain shah

2
Використовуючи це створює всередині onResume у фрагменті робить цикл, як його уникнути?
Душа

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
що буде з фрагментом Id, я ніде не оголошував ідентифікатор фрагмента. Як і де це декларувати?
Нарендра Сінгх

Не можу використовуватись getActivity()у моїй діяльності. Чи варто використовувати Activity.this...?
Si8

@NarendraJi це лише FrameLayout id, де ви розміщуєте свої фрагменти в контейнері.
Lokesh

Видаліть цю додаткову підтяжку. Це доставило мені багато клопоту.
Абхішек

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

Ви не можете перезавантажити фрагмент, поки він додається до діяльності, де ви отримуєте " 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
Будь ласка, надайте свою відповідь чіткими описами. Не пишіть код, не дайте пояснення щодо коду, яким ви поділилися, щоб інші також могли зрозуміти, і це буде корисно. Я прошу вас прочитати розділ FAQ, щоб ефективно використовувати переповнення стека.
Санкар Ганеш

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

це буде працювати лише у випадку, коли ви використовуєте FragmentManagerдля ініціалізації фрагмента. Якщо у вас це як <fragment ... />у XML, він не зателефонує onCreateViewзнову. Витратив мої 30 хвилин, щоб зрозуміти це.


1

Ось, що я зробив, і це працювало для мене, я використовую firebase, і коли користувач входить у систему, я спершу хотів оновити поточний фрагмент, вам потрібно буде вимагати контекст від діяльності, оскільки фрагмент не має способу отримати контекст, якщо ви не встановите його з "Діяльність" або "Контекст тут" це код, який я використовував і працював на мові kotlin, я думаю, ви могли б використовувати те саме в класі 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

Використовуйте ContentProviderі завантажуйте ваші дані за допомогою "CursorLoader". З цією архітектурою ваші дані будуть автоматично завантажені при зміні бази даних. Використовуйте сторонні рамки для своїх ContentProvider- ви насправді не хочете їх реалізувати самостійно ...


0

У мене був той самий випуск, але жодне з перерахованого вище не працювало на моєму. або виникла проблема з backstack (після завантаження, коли користувач натиснув назад, він знову піде той самий фрагмент), або він не зателефонував до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 це мій клас Fragment 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) {

        }
    });

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

Запишіть viewpagerAdapter.notifyDataSetChanged (); в onResume () в MainActivity. Щасти :)


-2

Найпростіший спосіб

зробити загальнодоступний статичний метод, що містить viewpager.setAdapter

зробити адаптер і переглядач статичними

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

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

MainActivity.refreshFragments();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.