在事务提交之前可以将事务保存由Activity管理的后台栈中,并允许用户导航返回 transaction.replace(R.id.fragment_container,newFragment); transaction.addToBackStack(null); transaction.commit();
来自官网的图
封装一个Activity,继承它,在抽象方法中返回要添加的fragment
public abstract class SingleFragmentActivity extends AppCompatActivity { protected abstract Fragment createFragment(); @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); //将FrameLayout 容器视图装载为视图 setContentView(R.layout.activity_fragment); //获取Fragment管理器 // FragmentManager管理着fragment队列(事务操作着队列里面的fragement)和回退栈(管理多个事务) FragmentManager fm=getSupportFragmentManager(); // 向FragmentManager请求并获取fragment。其容器视图的ID=fragment的ID Fragment fragment=fm.findFragmentById(R.id.fragment_container); /*为什么要获取的fragment会存在于队列中呢? 设备旋转或回收内存时,Android会销毁Activity,而后重建时,会调用Activity.onCreate(...)方法。activity被销毁时,它的FragmentManager会将fragment队列保存下来。这样,activity重建时,新的FragmentManager会首先获取保存的队列,然后重建fragment队列,从而恢复到原来的状态。*/ if(fragment==null){ fragment=createFragment(); fm.beginTransaction() //add(...)方法是整个事务的核心,它含有两个参数: 容器视图资源ID和新创建的fragment .add(R.id.fragment_container,fragment) .commit(); /* 容器视图资源ID的作用有 1.告诉FragmentManager,fragment视图应该出现在activity视图的什么位置; 2.用作FragmentManager队列中fragment的唯一标识符。 */ } } } “@Override protected Fragment createFragment(){ return FragmentTest.newInstance(); } “ “ public static FragmentTest newInstance() { Bundle args = new Bundle(); CrimeListFragment fragment = new CrimeListFragment(); fragment.setArguments(args); return fragment; } “每个fragment都需要一个唯一的标识符 android:id提供唯一标识符 android:tag提供唯一的字符串 如果以上两个都没有,系统会使用其容器视图的ID
activity_fragment.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> activity间通过fragment返回结果 在fragment中可以startActivityForResult(Intent,int)和onActivityResult(int,int,Intent)但是没有setResult(int ,intent). 所以需要借助活动来调用getActivity.setResult(); fragment间的数据传递 设置目标fragment public void setFragment(fragment,requestCode) 传递数据给目标fragment getTargetFragment().onActivityResult(getTargetRequsetCode,resultCode,intent); argument 添加名为newInstance()的静态方法给Fragment类。在里面完成fragment实例的创建并调用Fragment.setArguments(Bundle)方法。 public class MyFragment extends Fragment{ ...... public static MyFragment newInstance(data){ Bundle args=new Bundle(); args.putSerializable(MY_DATA,data); MyFragment fragment=new MyFragment(); fragment.setArguments(agrs); return fragment; } }获取argument
@Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); data=getArguments().getSerializable(My_DATA); }存入Bundle的数据必须是可序列化的数据。比如基本类型,实现了Parcellable接口的对象,实现了Serializable接口的对象,以及一些Android 支持的特殊对象。具体查看Bundle类。
为什么要使用fragment argument呢?为什么不直接创建一个实例变量呢? 创建实例变量的方式并不可靠。因为,在操作系统重建fragment时,设备配置发生改变时, 用户暂时离开当前应用时,甚至操作系统按需回收内存时,任何实例变量都不复存在了。尤其是内存不够,操作系统强制杀掉应用的情况,可以说是无人能挡。