รีเฟรช Fragment เมื่อโหลดซ้ำ


111

ในแอปพลิเคชัน Android ฉันกำลังโหลดข้อมูลจาก Db เข้าไปTableViewในไฟล์Fragment. แต่เมื่อฉันโหลดซ้ำFragmentมันจะแสดงข้อมูลก่อนหน้านี้ ฉันสามารถเติมFragmentข้อมูลใหม่ด้วยข้อมูลปัจจุบันแทนข้อมูลก่อนหน้าได้หรือไม่


โปรดแสดงรหัสให้เราดู คุณโหลดข้อมูลของคุณที่ใดคุณเริ่มต้นแฟรกเมนต์ของคุณที่ไหนคุณเก็บค่าของคุณไว้ที่ไหน
AS

สิ่งนี้ควรแก้ปัญหาที่อธิบายไว้อย่างพอเพียง: stackoverflow.com/questions/6503189/…
Benjamin W.

โปรดระบุข้อมูลเพิ่มเติม - ข้อมูลโค้ด
nikvs

ลองใช้ Swipe-to-Refresh To Your App ดูที่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

[แก้ไข]

วิธีนี้ต้องการให้ Fragment มีแท็ก
ในกรณีที่คุณไม่มีวิธีการของ @ Hammer คือสิ่งที่คุณต้องการ


3
สิ่งนี้ทำให้เกิดข้อผิดพลาดต่อไปนี้ - java.lang.RuntimeException: ความล้มเหลวในการส่งผลลัพธ์ ResultInfo {who = null, request = 2, result = 3, data = null} ไปยัง activity {xont.virtusel.v4.controller / xont.virtusel.v4.controller .sale.InvocieBrandActivity}: java.lang.IllegalStateException: ไม่สามารถดำเนินการนี้หลังจาก onSaveInstanceState
Samantha Withanage

1
@Elizabeth ตรวจสอบให้แน่ใจว่า Fragment ของคุณมีการตั้งค่าแท็กอย่างถูกต้อง
Phantômaxx

1
@Rotwang ขอบคุณสำหรับการตอบกลับของคุณฉันเพิ่งใช้ทางลัดแทนที่จะทำโค้ดยาว ๆ แต่นั่นช่วยปูทาง :)
Si8

1
โซลูชันนี้ไม่ทำงานอีกต่อไปในเวอร์ชันใหม่ของ support-v4-library (25.1.0) คำอธิบายที่นี่: stackoverflow.com/questions/41270858/…
Brahim Bouaboud

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

1
จะใส่รหัสนี้ไว้ที่ไหน? ภายในกิจกรรมหรือส่วนของตัวเอง?
Narendra Singh

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
จะเป็นรหัสชิ้นส่วนอะไรฉันยังไม่ได้ประกาศรหัสส่วนใดเลย ประกาศอย่างไรและที่ไหน?
Narendra Singh

ดูเหมือนจะใช้getActivity()ในกิจกรรมของฉันไม่ได้ ฉันควรใช้Activity.this...?
Si8

@NarendraJi เป็นรหัส FrameLayout เท่านั้นที่เป็นที่ที่คุณวางชิ้นส่วนของคุณในคอนเทนเนอร์
Lokesh

โปรดลบวงเล็บเสริมนั้นออก มันสร้างความเดือดร้อนให้กับฉันมาก
Abhishek

9

คุณสามารถรีเฟรชส่วนของคุณเมื่อผู้ใช้มองเห็นได้เพียงแค่เพิ่มรหัสนี้ลงใน Fragment ของคุณสิ่งนี้จะรีเฟรชส่วนของคุณเมื่อมองเห็นได้

@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 วินาทีกว่าจะโหลดใหม่
Omar Boshra

ดูเหมือนว่าจะใช้งานได้ดีกับอะแดปเตอร์ viewpager
DragonFire

2
setUserVisibleHint เลิกใช้แล้ว
Sai Aditya

ทำงานให้ฉันขอบคุณสำหรับการแก้ปัญหา
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
โปรดให้คำตอบของคุณพร้อมคำอธิบายที่ชัดเจน อย่าเขียนโค้ดให้คำอธิบายเกี่ยวกับโค้ดที่คุณแชร์เพื่อให้คนอื่นเข้าใจด้วยและจะเป็นประโยชน์ ฉันขอให้คุณอ่านส่วนคำถามที่พบบ่อยเพื่อใช้ Stack Overflow อย่างมีประสิทธิภาพ
Sankar Ganesh

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

สิ่งนี้จะใช้ได้เฉพาะเมื่อคุณใช้FragmentManagerเพื่อเริ่มต้นส่วน หากคุณมีเป็น<fragment ... />XML จะไม่เรียกonCreateViewอีกครั้ง เสียเวลาไป 30 นาทีเพื่อคิดออก


1

สิ่งที่ฉันทำและมันใช้ได้ผลสำหรับฉันฉันใช้ firebase และเมื่อผู้ใช้ล็อกอินฉันต้องการรีเฟรช Fragment ปัจจุบันก่อนคุณจะต้องร้องขอบริบทจากกิจกรรมเนื่องจากแฟรกเมนต์ไม่มีวิธีรับบริบทเว้นแต่คุณจะตั้งค่าจากกิจกรรมหรือบริบทที่นี่ เป็นรหัสที่ฉันใช้และทำงานในภาษา 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()
        }
    }

}

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

GeneralInfo มันคือคลาส Fragment ของฉัน GeneralInfo.java

ฉันวางไว้เป็นวิธีการในคลาส Fragment:

public void Reload(){
    getActivity().getSupportFragmentManager().beginTransaction().replace(LogActivity.this.getId(), new LogActivity()).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

ตัวอย่างเช่นกับ 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

วิธีที่ง่ายที่สุด

สร้างวิธีการแบบคงที่สาธารณะที่มี viewpager.setAdapter

ทำให้อะแดปเตอร์และ viewpager คงที่

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

โทรได้ทุกที่กิจกรรมใด ๆ ชิ้นส่วนใด ๆ

MainActivity.refreshFragments();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.