Android Fragemnt重疊

1、閒聊

        今天測試突然給我提出了一個bug,我特麼當時就懵逼了!What?什麼鬼?寫一個項目結構寫出來了一個bug!然後我就去看,我越看越懵逼這樣寫沒錯啊!我實在看不出來,算了看一下生命週期吧!好吧,寫一個測試dome,來打印一下生命週期:

onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{8626570 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{ec4200f #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{5e0689c #2 id=0x7f0b006c tab3}
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{9d97288 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{fab6421 #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{701e046 #2 id=0x7f0b006c tab3}
onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{2dd30cc #3 id=0x7f0b006c tab1}
onRestoreInstanceState: --------------------
onAttachFragment: --------------------Tab2Fragment{6d41f15 #4 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{907d22a #5 id=0x7f0b006c tab3}
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{6649791 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{a28e6f6 #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{20d7af7 #2 id=0x7f0b006c tab3}
onAttachFragment: --------------------Tab1Fragment{d3ecd64 #3 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{5aa1bcd #4 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{b747c82 #5 id=0x7f0b006c tab3}
onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{420d4e8 #6 id=0x7f0b006c tab1}
onRestoreInstanceState: --------------------

        自大了,光看肯定看不出毛病的!有了生命週期我們就可以瞭解原理咯。可以看出來我每次進入後臺時都會執行onSaveInstanceState方法,
我每次從後臺回到頁面時會依次執行:onAttachFragmentonCreateonSaveInstanceState這三個我需要的方法!到了這裏我的想法是onSaveInstanceState這個方法在onAttachFragmentonCreate這兩個方法的後面,我個人肯定不願意在這裏取出數據,因爲我出現的這個bug是在活動銷燬後纔會出現的bug!每次肯定會走onCreate,所以我更願意在onCreate方法中取出數據,但是這個東西的看你們的喜好,onAttachFragment這個方法中取出Fragment也是非常方便的,至少比onCreate方便,如:

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if (null != fragment && fragment instanceof Tab3Fragment) {
        tab3Fragment = (Tab3Fragment) fragment;
    }
    Log.d(TAG, "onAttachFragment: --------------------" + fragment);
}

在看一下在onCreate中取數據:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test_fragment);
    if (null != savedInstanceState) {
        FragmentManager fragmentManager = getFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(tabs[1]);
        if (null != fragment && fragment instanceof Tab1Fragment) {
            tab1Fragment = (Tab1Fragment) fragment;
        }
    }
}

        可以看出來了吧,onCreate方法中要多一個步奏來獲取fragment,好了就聊到這兒!我們開始說具體怎樣解決這個問題。

2、解決問題

        解決問題的方法肯定不止一種,這裏我只說一種:我這裏在使用FragmentTransaction(Fragment管理器)的時候,爲每一個需要添加顯示的Fragment打上一個 #tag 標記,再退出後臺情況下,活動被銷燬後,通過FragmentTransaction去取出對應 tag 存儲的 Fragment,當然我這兒還存了一個索引值:index(退出後臺時,顯示的第幾個fragment)!那就上代碼了:


退出時保存 index:
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(tabs[0], index);
    Log.d(TAG, "onSaveInstanceState: --------------------");
}

從新進入頁面時,取出狀態及fragment:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test_fragment);
    Log.d(TAG, "onCreate: --------------------");
    if (null != savedInstanceState) {
        index = savedInstanceState.getInt(tabs[0], 1);
        FragmentManager fragmentManager = getFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(tabs[1]);
        if (null != fragment && fragment instanceof Tab1Fragment) {
            tab1Fragment = (Tab1Fragment) fragment;
        }
        fragment = fragmentManager.findFragmentByTag(tabs[2]);
        if (null != fragment && fragment instanceof Tab2Fragment) {
            tab2Fragment = (Tab2Fragment) fragment;
        }
        fragment = fragmentManager.findFragmentByTag(tabs[3]);
        if (null != fragment && fragment instanceof Tab3Fragment) {
            tab3Fragment = (Tab3Fragment) fragment;
        }
    }
    showTab(index);
    init();
}

我們現在再來看一看生命週期:
onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{c577bb3 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{61d116e #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{ec4200f #2 id=0x7f0b006c tab3}
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{facae2b #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{9d97288 #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{fab6421 #2 id=0x7f0b006c tab3}
onCreate: --------------------
onRestoreInstanceState: --------------------
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{6d41f15 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{907d22a #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{d9781b #2 id=0x7f0b006c tab3}
onCreate: --------------------
onRestoreInstanceState: --------------------

        現在這個東西看着就非常清晰了吧!再也沒有多次創建fragment了,那麼這問題就算圓滿解決了!

3、源碼

public class TestFragmentActivity extends AppCompatActivity {
    private static final String TAG = "TestFragmentActivity";
    private Tab1Fragment tab1Fragment;
    private Tab2Fragment tab2Fragment;
    private Tab3Fragment tab3Fragment;
    private int index = 1;
    private String[] tabs = {"index", "tab1", "tab2", "tab3"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_fragment);
        Log.d(TAG, "onCreate: --------------------");
        if (null != savedInstanceState) {
            index = savedInstanceState.getInt(tabs[0], 1);
            FragmentManager fragmentManager = getFragmentManager();
            Fragment fragment = fragmentManager.findFragmentByTag(tabs[1]);
            if (null != fragment && fragment instanceof Tab1Fragment) {
                tab1Fragment = (Tab1Fragment) fragment;
            }
            fragment = fragmentManager.findFragmentByTag(tabs[2]);
            if (null != fragment && fragment instanceof Tab2Fragment) {
                tab2Fragment = (Tab2Fragment) fragment;
            }
            fragment = fragmentManager.findFragmentByTag(tabs[3]);
            if (null != fragment && fragment instanceof Tab3Fragment) {
                tab3Fragment = (Tab3Fragment) fragment;
            }
        }
        showTab(index);
        init();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(tabs[0], index);
        Log.d(TAG, "onSaveInstanceState: --------------------");
    }

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        Log.d(TAG, "onAttachFragment: --------------------" + fragment);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onRestoreInstanceState: --------------------");
    }

    private void init() {
        findViewById(R.id.tv_tab1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showTab(1);
            }
        });
        findViewById(R.id.tv_tab2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showTab(2);
            }
        });
        findViewById(R.id.tv_tab3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showTab(3);
            }
        });
    }

    private void showTab(int index) {
        this.index = index;
        // 開啓一個Fragment事務
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        hideFragment(transaction);
        switch (index) {
            case 1:
                if (null == tab1Fragment) {
                    tab1Fragment = new Tab1Fragment();
                    transaction.add(R.id.fragment, tab1Fragment, tabs[index]);
                } else {
                    transaction.show(tab1Fragment);
                }
                break;
            case 2:
                if (null == tab2Fragment) {
                    tab2Fragment = new Tab2Fragment();
                    transaction.add(R.id.fragment, tab2Fragment, tabs[index]);
                } else {
                    transaction.show(tab2Fragment);
                }
                break;
            case 3:
                if (null == tab3Fragment) {
                    tab3Fragment = new Tab3Fragment();
                    transaction.add(R.id.fragment, tab3Fragment, tabs[index]);
                } else {
                    transaction.show(tab3Fragment);
                }
                break;
        }
        transaction.commit();
    }

    private void hideFragment(FragmentTransaction transaction) {
        if (null != tab1Fragment) {
            transaction.hide(tab1Fragment);
        }
        if (null != tab2Fragment) {
            transaction.hide(tab2Fragment);
        }
        if (null != tab3Fragment) {
            transaction.hide(tab3Fragment);
        }
    }
}

        至此問題已解決!有問題即時反饋,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章