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方法,
我每次從後臺回到頁面時會依次執行:onAttachFragment,onCreate,onSaveInstanceState這三個我需要的方法!到了這裏我的想法是onSaveInstanceState這個方法在onAttachFragment,onCreate這兩個方法的後面,我個人肯定不願意在這裏取出數據,因爲我出現的這個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);
}
}
}
至此問題已解決!有問題即時反饋,謝謝!