为什么需要判null呢?主要是因为,当Activity因为配置发生改变(屏幕旋转)或者内存不足被系统杀死,造成重新创建时,我们的fragment会被保存下来,但是会创建新的FragmentManager,新的FragmentManager会首先会去获取保存下来的fragment队列,重建fragment队列,从而恢复之前的状态。
希望保留用户操作的面板,你可以使用hide和show;我不希望保留用户操作,你可以使用remove(),然后add()
remove和detach有一点细微的区别,在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。那么二者怎么取舍使用呢?如果你的当前Activity一直存在,那么在不希望保留用户操作的时候,你可以优先使用detach。
管理Fragment回退栈:
如何添加一个Fragment事务到回退栈:FragmentTransaction.addToBackStack(String)
例子:
MainActivity.java直接将FragmentOne添加到布局文件中的FrameLayout中,注意这里并没有调用FragmentTransaction.addToBackStack(String),因为我不喜欢在当前显示时,点击Back键出现白板。
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
<strong>tx.add(R.id.id_content, new FragmentOne(),"ONE"); </strong>
tx.commit();
}
接下来FragmentOne
@Override
public void onClick(View v)
{
FragmentTwo fTwo = new FragmentTwo();
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
<strong>tx.replace(R.id.id_content, fTwo, "TWO");
tx.addToBackStack(null); </strong>
tx.commit();
}
我们在点击 FragmentOne 中的按钮时,使用了 replace 方法,如果你看了前一篇博客,一定记得 replace 是 remove 和 add 的合体,并且如果不添加事务到回退栈,前一个 Fragment 实例会被销毁。这里很明显,我们 调用 tx.addToBackStack(null); 将当前的事务添加到了回退栈,所以 FragmentOne 实例不会被销毁 ,但是视图层次依然会被销毁,即会调用 onDestoryView 和 onCreateView( 就是这里 没有保留用户操作 )
接下来FragmentTwo---这里保留了用户操作
public void onClick(View v)
{
FragmentThree fThree = new FragmentThree();
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
<strong> tx.hide(this);
tx.add(R.id.id_content , fThree, "THREE");
// tx.replace(R.id.id_content, fThree, "THREE");
tx.addToBackStack(null);</strong>
tx.commit();
}
如何处理运行时配置发生变化:只有在savedInstanceState==null时,才进行创建Fragment实例
屏幕发生旋转,当你的应用被至于后台(例如用户点击了home),长时间没有返回的时候,你的应用也会被重新启动。比如上例:如果你把上面的例子你至于FragmentThree界面,然后处于后台状态,长时间后你会发现当你再次通过home打开时,上面FragmentThree与FragmentOne叠加在一起
Fragment Arguments:Fragment 和activity解耦
有哥们会说,这个简单?看我的代码(问题代码):
public class ContentFragment extends Fragment
{
private String mArgument ;
public static final String ARGUMENT ="argument";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
<del> mArgument = getActivity().getIntent().getStringExtra(ARGUMENT); </del>
}
我们直接在Fragment的onCreate中,拿到宿主Activty,宿主Activity中肯定能通过getIntent拿到Intent,然后通过get方法,随意拿参数~~
这么写,功能上是实现了,但是呢?存在一个大问题:我们用Fragment的一个很大的原因,就是为了复用。你这么写,相当于这个Fragment已经完全和当前这个宿主Activity绑定了,复用直接废了~~~所以呢?我们换种方式,推荐使用arguments来创建Fragment。
<span style="color:#333333;">public class ContentFragment extends Fragment
{
private String mArgument;
public static final String ARGUMENT = "argument";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// mArgument = getActivity().getIntent().getStringExtra(ARGUMENT);
Bundle bundle = getArguments();
if (bundle != null)
mArgument = bundle.getString(ARGUMENT);
}
/**
* 传入需要的参数,设置给arguments
*/
public static ContentFragment newInstance(String argument)
{
</span><span style="color:#ff0000;"> Bundle bundle = new Bundle();
bundle.putString(ARGUMENT, argument);
ContentFragment contentFragment = new ContentFragment();
contentFragment.setArguments(bundle); </span><span style="color:#333333;">
return contentFragment;
} </span>
Fragment的startActivityForResult
- Intent intent = new Intent();
- intent.putExtra(RESPONSE, "good");
- getActivity().setResult(ListTitleFragment.REQUEST_DETAIL, intent);
FragmentPagerAdapter与FragmentStatePagerAdapter
主要区别就在与对于fragment是否销毁,下面细说:
FragmentPagerAdapter:对于不再需要的fragment,选择调用detach方法,仅销毁视图,并不会销毁fragment实例。
FragmentStatePagerAdapter:会销毁不再需要的fragment,当当前事务提交以后,会彻底的将fragmeng从当前Activity的FragmentManager中移除,state标明,销毁时,会将其onSaveInstanceState(Bundle outState)中的bundle信息保存下来,当用户切换回来,可以通过该bundle恢复生成新的fragment,也就是说,你可以在onSaveInstanceState(Bundle outState)方法中保存一些数据,在onCreate中进行恢复创建。
如上所说,使用FragmentStatePagerAdapter当然更省内存,但是销毁新建也是需要时间的。一般情况下,如果你是制作主页面,就3、4个Tab,那么可以选择使用FragmentPagerAdapter,如果你是用于ViewPager展示数量特别多的条目时,那么建议使用FragmentStatePagerAdapter。