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);
}
}
}
至此问题已解决!有问题即时反馈,谢谢!