1. Fragment的生命周期
Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。下面这张图很好的解释了两者生命周期的关系。
2. 静态的使用Fragment
把Fragment当成普通的控件,直接写在Activity的布局文件中。
Activity的布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/id_fragment_title"
android:name="com.app.fragments.TitleFragment"
android:layout_width="fill_parent"
android:layout_height="45dp" />
<fragment
android:layout_below="@id/id_fragment_title"
android:id="@+id/id_fragment_content"
android:name="com.app.fragments.ContentFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
这样把Fragment当成普通的View一样声明在Activity的布局文件中,然后所有控件的事件处理等代码都由各自的Fragment去处理。
3. 动态的使用Fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RadioGroup
android:id="@+id/rg"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:gravity="center"
>
<RadioButton
android:id="@+id/rb_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="菜单1"
android:checked="true"
android:gravity="center"
/>
<RadioButton
android:id="@+id/rb_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="菜单2"
android:gravity="center"
/>
<RadioButton
android:id="@+id/rb_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="菜单3"
android:gravity="center"
/>
<RadioButton
android:id="@+id/rb_4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="菜单4"
android:gravity="center"
/>
</RadioGroup>
<FrameLayout
android:id="@+id/id_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/rg"
></FrameLayout>
</RelativeLayout>
对RadioButton进行监听:
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction transaction=fm.beginTransaction();
switch (checkedId){
case R.id.rb_1:
if(menuOneFragment==null){
menuOneFragment=new MenuOneFragment();
}
transaction.replace(R.id.id_content, menuOneFragment);
break;
case R.id.rb_2:
if(menuTwoFragment==null){
menuTwoFragment=new MenuTwoFragment();
}
transaction.replace(R.id.id_content,menuTwoFragment);
break;
case R.id.rb_3:
if(menuThreeFragment==null){
menuThreeFragment=new MenuThreeFragment();
}
transaction.replace(R.id.id_content, menuThreeFragment);
break;
case R.id.rb_4:
if(menuFourFragment==null){
menuFourFragment=new MenuFourFragment();
}
transaction.replace(R.id.id_content, menuFourFragment);
break;
}
transaction.commit();
}
4. Fragment家族常用的API
获取FragmentManage的方式:
getFragmentManager() // v4中,getSupportFragmentManagerFragmentTransaction的方法
FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务transaction.add()
往Activity中添加一个Fragmenttransaction.remove()
从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。transaction.replace()
使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~transaction.hide()
隐藏当前的Fragment,仅仅是设为不可见,并不会销毁transaction.show()
显示之前隐藏的Fragmenttransatcion.commit()
提交一个事务,注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。当activity再次被恢复时commit之后的状态将丢失。如果丢失也没关系,那么使用commitAllowingStateLoss()方法。当屏幕旋转时如何处理:
当你的应用被至于后台(例如用户点击了home),长时间没有返回的时候,你的应用也会被重新启动。
当屏幕发生旋转,Activity发生重新启动,默认的Activity中的Fragment也会跟着Activity重新创建;这样造成当旋转的时候,本身存在的Fragment会重新启动,然后当执行Activity的onCreate时,又会再次实例化一个新的Fragment,这就是出现的原因。
其实通过检查onCreate的参数Bundle savedInstanceState就可以判断,当前是否发生Activity的重新创建:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Log.e(TAG, savedInstanceState+"");
if(savedInstanceState == null)
{
mFOne = new FragmentOne();
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
tx.add(R.id.id_content, mFOne, "ONE");
tx.commit();
}
}
Fragment Arguments
比如我们某个按钮触发Activity跳转,需要通过Intent传递参数到目标Activity的Fragment中,那么此Fragment如何获取当前的Intent的值呢?
public class MenuOneFragment extends Fragment{
private String mArgument;
public static final String ARGUMENT = "argument";
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle=getArguments();
if(bundle!=null){
mArgument=bundle.getString(ARGUMENT);
}
}
public static MenuOneFragment newInstance(String argument){
Bundle bundle=new Bundle();
bundle.putString(ARGUMENT,argument);
MenuOneFragment menuOneFragment=new MenuOneFragment();
menuOneFragment.setArguments(bundle);
return menuOneFragment;
}
}
注意:setArguments方法必须在fragment创建以后,添加给Activity前完成。千万不要,首先调用了add,然后设置arguments。
链接:
Android Fragment 你应该知道的一切
Android 官方推荐 : DialogFragment 创建对话框
Android Fragment应用实战,使用碎片向ActivityGroup说再见