Fragment的优点:有生命周期的概念、可以作为View使用
生命周期、使用方式、hide、show、attach、detach、remove、add、replace作用:
我们可以把Fragment当成Activity界面的一个组成部分,甚至Activity的界面可以完全由不同的Fragment组成,而且Fragment拥有自己的生命周期并能进行事件处理,这样就不必在Activity中写一堆事件处理逻辑了,更为重要的是,你可以动态的添加、替换和移除某个Fragment
静态的使用Fragment:
这是使用Fragment最简单的一种方式,把Fragment当成普通的控件,直接写在Activity的布局文件中:继承Fragment,重写onCreateView决定Fragment的布局、在布局文件中使用Fragment
动态的使用Fragment:
FragmentManager fm = getFragmentManager(); //Fragment里面需要调用getChildFragmentManager
FragmentTransaction transaction = fm.beginTransaction();
transaction.commit();
Fragment家族常用API
android.app.Fragment 主要用于定义Fragment
android.app.FragmentManager 主要用于在Activity中操作Fragment
android.app.FragmentTransaction 保证一些列Fragment操作的原子性
FragmentTransaction方法
开启事务:FragmentTransaction transaction = fm.beginTransatcion();
添加Fragment:transaction.add()
移除Fragment:transaction.remove()
替换Fragment,实际上就是remove()然后add():transaction.replace()
隐藏Fragment,仅仅是设为不可见,并不会销毁:transaction.hide()
显示之前隐藏的Fragment:transaction.show()
销毁view视图 ,和remove()不同,此时fragment的状态依然由FragmentManager维护:detach()
重建view视图,附加到UI上并显示:attach()
提交一个事务:transatcion.commit()
switch(msg.what) {
case1:
fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.framelayout,blankFragmentOne);
fragmentTransaction.commit();
break;
case 2:
fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.detach(blankFragmentOne);
fragmentTransaction.commit();
break;
case 3:
fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.attach(blankFragmentOne);
fragmentTransaction.commit();
break;
}
- 09-13 09:46:12.489 26270-26270/com.example.wangzihan.myapplication E/parachute: onAttach 1
- 09-13 09:46:12.489 26270-26270/com.example.wangzihan.myapplication E/parachute: onCreate 1
- 09-13 09:46:12.490 26270-26270/com.example.wangzihan.myapplication E/parachute: onCreateView 1
- 09-13 09:46:12.515 26270-26270/com.example.wangzihan.myapplication E/parachute: onActivityCreated 1
- 09-13 09:46:12.515 26270-26270/com.example.wangzihan.myapplication E/parachute: onStart 1
- 09-13 09:46:12.515 26270-26270/com.example.wangzihan.myapplication E/parachute: onResume 1
- 09-13 09:46:14.488 26270-26270/com.example.wangzihan.myapplication E/parachute: onPause 1
- 09-13 09:46:14.489 26270-26270/com.example.wangzihan.myapplication E/parachute: onStop 1
- 09-13 09:46:14.490 26270-26270/com.example.wangzihan.myapplication E/parachute: onDestroyView 1
- 09-13 09:46:16.490 26270-26270/com.example.wangzihan.myapplication E/parachute: onCreateView 1
- 09-13 09:46:16.495 26270-26270/com.example.wangzihan.myapplication E/parachute: onActivityCreated 1
- 09-13 09:46:16.496 26270-26270/com.example.wangzihan.myapplication E/parachute: onStart 1
- 09-13 09:46:16.496 26270-26270/com.example.wangzihan.myapplication E/parachute: onResume 1
switch(msg.what) {
case1:
fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.framelayout,blankFragmentOne);
fragmentTransaction.commit();
break;
case 2:
fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.remove(blankFragmentOne);
fragmentTransaction.commit();
break;
case 3:
fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.framelayout,blankFragmentOne);
fragmentTransaction.commit();
break;
}
- 09-13 09:48:35.027 28354-28354/com.example.wangzihan.myapplication E/parachute: onAttach 1
- 09-13 09:48:35.027 28354-28354/com.example.wangzihan.myapplication E/parachute: onCreate 1
- 09-13 09:48:35.028 28354-28354/com.example.wangzihan.myapplication E/parachute: onCreateView 1
- 09-13 09:48:35.035 28354-28354/com.example.wangzihan.myapplication E/parachute: onActivityCreated 1
- 09-13 09:48:35.035 28354-28354/com.example.wangzihan.myapplication E/parachute: onStart 1
- 09-13 09:48:35.035 28354-28354/com.example.wangzihan.myapplication E/parachute: onResume 1
- 09-13 09:48:37.027 28354-28354/com.example.wangzihan.myapplication E/parachute: onPause 1
- 09-13 09:48:37.027 28354-28354/com.example.wangzihan.myapplication E/parachute: onStop 1
- 09-13 09:48:37.028 28354-28354/com.example.wangzihan.myapplication E/parachute: onDestroyView 1
- 09-13 09:48:37.030 28354-28354/com.example.wangzihan.myapplication E/parachute: onDestroy 1
- 09-13 09:48:37.031 28354-28354/com.example.wangzihan.myapplication E/parachute: onDetach 1
- 09-13 09:48:39.028 28354-28354/com.example.wangzihan.myapplication E/parachute: onAttach 1
- 09-13 09:48:39.028 28354-28354/com.example.wangzihan.myapplication E/parachute: onCreate 1
- 09-13 09:48:39.028 28354-28354/com.example.wangzihan.myapplication E/parachute: onCreateView 1
- 09-13 09:48:39.040 28354-28354/com.example.wangzihan.myapplication E/parachute: onActivityCreated 1
- 09-13 09:48:39.040 28354-28354/com.example.wangzihan.myapplication E/parachute: onStart 1
- 09-13 09:48:39.040 28354-28354/com.example.wangzihan.myapplication E/parachute: onResume 1
hide和show只会出发onHiddenChanged回调
FragmentTransaction.addToBackStack(String),把Transaction添加到回退栈,这样按返回键时,会执行popBackStack将Transaction从回退栈中移除,并执行Transaction的反向操作,另外,加到回退栈中的remove只是只是执行了detach操作,不会执行onDestory和onDetach
Fragment与Activity通信
因为所有的Fragment都是依附于Activity的,所以通信起来并不复杂,大概归纳为:
a、如果你Activity中包含自己管理的Fragment的引用,可以通过引用直接访问所有的Fragment的public方法
b、如果Activity中未保存任何Fragment的引用,每个Fragment都有一个唯一的TAG或者ID,可以通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得任何Fragment实例,然后进行操作
c、在Fragment中可以通过getActivity得到当前绑定的Activity的实例,然后进行操作
<fragment
android:id="@+id/aaa"
android:tag="bbb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:name="cn.example.bjwangzihan.myapplication.MyFragment"/>
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(fragment1);
fragmentTransaction.commit();
FragmentTransaction fragmentTransaction2 = fragmentManager.beginTransaction();
fragmentTransaction2.add(fragment1,"bbb");
fragmentTransaction2.commit();
add的时候需要附带TAG信息,XML文件中可以声明id和tag信息
Fragment注意事项(主要涉及到销毁重建的场景):
fragment的获取一定要通过FragmentManager,可以用findFragmentWithTag或者getFragments来得到特定或者所有fragment,如果没有获取到fragment实例再去创建,否则销毁重建的情况下调用getContext时会报mHost空指针异常
如果是通过ViewPager来间接控制Fragment更要注意,传给FragmentPagerAdapter的Fragment实例一定要和FragmentManager中的一致,如果FragmentManager中没有再去创建
Fragment的子类的构造函数务必要保证有无参构造函数,否则在restore时出现"androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment : could not find Fragment constructor",具体参考下面的Fragment实例化源码:
Fragment传参的正确姿势:
Bundle args = new Bundle();
args.putInt("index", index);//把参数放在Bundle
f.setArguments(args);