簡體   English   中英

應用被殺死並恢復后,如何避免Activity中出現多個片段實例?

[英]How to avoid multiple instances of fragments in Activity after app is killed and resumed?

我有一個帶有主屏幕的應用程序,該屏幕具有2個片段(目前)和一個導航抽屜。 目前,我在啟動時加載片段A(瀏覽),並在單擊時加載片段B。 從那時起,我顯示和隱藏片段。 它比每次單擊重新創建片段快,而我的片段A需要一些時間來加載。

我注意到,當我轉到片段B並從那里轉到另一個活動(稱為活動2)並離開應用程序並等待其被殺死(或執行某些瘋狂的操作(如更改設備語言))之后,回到相同的活動,它仍然存在。 當我按回去回到片段B時,有時(50%的時間)將片段B繪制在片段A上。單擊抽屜中的片段A時,片段A看起來很好,但是單擊片段B時,還有另一個實例片段A並在片段B的頂部。

我在這個問題上花了超過2天的時間,卻一無所獲。

這是我選擇片段的代碼:

private void selectItem(int position, boolean addExploreFragment) {
    Log.d(tag, "selectItem: " + position);

    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

    //add explore fragment - this is called on app startup, but also when the app is killed and resumed which results in 2 explore fragments

    if (addExploreFragment){

        fragmentTransaction.replace(R.id.content_frame, mExploreFragment, EXPLORE_FRAGMENT_TAG);
        Log.d(tag, "Replaced frame and added "+ mFragmentTags[position]);

    } else {
        //add fragment for the first time
        if (getSupportFragmentManager().findFragmentByTag(mFragmentTags[position]) == null && position != 0) {
            fragmentTransaction.add(R.id.content_frame, mFragments[position], mFragmentTags[position]);
            Log.d(tag, "Added Fragment: "+ mFragmentTags[position]);
        }
        //shows and hides fragments
        for (int i = 0; i < mFragments.length; i++) {
            if (i == position) {
                fragmentTransaction.show(mFragments[i]);
                Log.d(tag, "Showing Fragment: "+ mFragmentTags[i]);
            } else {
                if (getSupportFragmentManager().findFragmentByTag(mFragmentTags[i]) != null) {
                    fragmentTransaction.hide(mFragments[i]);
                    Log.d(tag, "Hid Fragment: "+ mFragmentTags[i]);
                }
            }
        }

    }

    fragmentTransaction.commit();
    //not null check for calling selectItem(0) before loading the drawer
    if (mDrawerList != null){
        mDrawerList.setItemChecked(position, true);
    }
}

我肯定知道,exploration片段被創建了兩次,並且兩個實例的行為彼此獨立(只是共享)。

我迷路了下一步。 在低端設備上可以很容易地重現此問題,但在Nexus 4(我的測試設備)等設備上,可以通過更改設備語言來重現此問題。

有人對此有任何想法嗎? 基本上,如果已經有一個explorationFragment時沒有調用addExploreFragment塊,那么我認為可以解決此問題,但我一直無法做到。 另外,我嘗試刪除所有片段,然后添加explorerFragment,但發生相同的事情(50%的時間)。

謝謝! 很長的帖子,對不起,我覺得我應該分享所有細節。

更新 :當我更改設備語言並返回到活動2上的應用程序並返回到主頁活動時,它打開了很好的片段B,但是由於片段很重,因此片段A被重新創建,系統可能已將其刪除從記憶里。 同樣,如果系統將其刪除,則可以重新創建它,這是可以的,但是為什么在不刪除它的情況下可以重新創建它。 我相信這與我的代碼有關,每次嘗試第二次(不關閉應用程序)時,都會發生2次重碎片A實例。

但fragmentTransaction.replace不應刪除所有先前添加的片段,然后添加explorFragment。 它不是那樣工作的。 片段A和片段B都不會被刪除。

我發現了一些新東西,對我來說很奇怪。 當您使用fragmentTransaction.add ,上一個片段上具有的偵聽器 (如DrawerItemClickListener) 仍處於活動狀態 即使您使用fragmentTransaction.commit也是如此。

所以...我懷疑使用add方法時,實際上是單擊了另一個隱藏按鈕或隱藏的UI,該按鈕或隱藏的UI在前一個片段上具有事件偵聽器。 我當然不喜歡這樣,效果可能會很混亂。 是的,這發生在我身上,我有一段時間不明白為什么。

就目前而言,我認為最簡單的代碼修復將是使用replace方法而不是add replace()使偵聽器處於非活動狀態。 如果有效,則可以進行更好/更優雅的修復。

讓我知道發生什么事....

我開始注意到你的帖子

當我去片段B參加另一項活動時

交互或啟動另一個活動時,將啟動一組新的片段。 看看這個Google網頁@ Fragments Lifecycle 為了澄清我的主張,有一句話說

片段必須始終嵌入到活動中,並且片段的生命周期直接受到宿主活動的生命周期的影響。

您最好至少閱讀其中幾段。

我不確定您的解決方案應該是什么。 也許使片段在您擁有的兩個活動之間具有區別,不同和清晰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM