学而不思则罔,思而不学则殆
Fragment是一种可以嵌套在Activity当中的UI片段。
https://github.com/aJanefish/FragmentDemo
1.自定义Fragment
//left_fragment.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray"> <Button android:id="@+id/left_fragment_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是左fragment" /> </androidx.constraintlayout.widget.ConstraintLayout> //LeftFragment.java public class LeftFragment extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.left_fragment, container, false); } } //right_fragment.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是右边的fragment" /> </androidx.constraintlayout.widget.ConstraintLayout> //RightFragment .java public class RightFragment extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.right_fragment, container, false); } }2.布局中注册两个fragment 通过{android:name}引用Fragment
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="horizontal" tools:context=".activity.XmlActivity"> <fragment android:id="@+id/activity_xml_left" android:name="com.example.fragmentdemo.fragment.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:id="@+id/activity_xml_right" android:name="com.example.fragmentdemo.fragment.RightFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>3.展示效果
1.在自定义一个Fragment
//another_right_fragment.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我另一个Fragment" /> </androidx.constraintlayout.widget.ConstraintLayout> //AnotherRightFragment.java public class AnotherRightFragment extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.another_right_fragment, container, false); } }2.定义容器
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context=".activity.JavaUseFragmentActivity"> <fragment android:id="@+id/activity_java_use_fragment_left" android:name="com.example.fragmentdemo.fragment.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <!--Fragment的容器--> <FrameLayout android:id="@+id/activity_java_use_fragment_fl" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>3.动态替换fragment
public class JavaUseFragmentActivity extends AppCompatActivity { boolean flag = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_java_use_fragment); Button button = findViewById(R.id.left_fragment_button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (flag) { replaceFragment(new AnotherRightFragment()); } else { replaceFragment(new RightFragment()); } flag = !flag; } }); } private void replaceFragment(Fragment fragment) { //获取FragmentManager FragmentManager fragmentManager = getSupportFragmentManager(); //开启一个事务 FragmentTransaction beginTransaction = fragmentManager.beginTransaction(); //向容器添加或者替换Fragment beginTransaction.replace(R.id.activity_java_use_fragment_fl, fragment); //提交事务 beginTransaction.commit(); } }动态添加Fragment主要分为5步:
创建一个Fragment的实例获取FragmentManager开启一个事务向容器添加或者替换Fragment提交事务效果如下: 开始时容器中没有Fragment,效果为1,点击后添加Fragment到容器中了,就是2 和 3的切换
在上一节的测试中,实现了向Activity中动态添加Fragment的功能。不过你尝试一下就会发现。通过点击按钮添加了一个Fragment之后,这是按下返回键,该页面就会自动退出。如果我们想实现类似返回栈的效果,按下Back键后,回到上一个Fragment,该如何实现呢? 其实很简单,FragmentTransaction 中提供了addToBackStack()方法,可以用于将一个事务添加到返回栈中。代码如下:
private void replaceFragment(Fragment fragment) { //获取FragmentManager FragmentManager fragmentManager = getSupportFragmentManager(); //开启一个事务 FragmentTransaction beginTransaction = fragmentManager.beginTransaction(); //向容器添加或者替换Fragment beginTransaction.replace(R.id.activity_java_use_fragment_fl, fragment); //加入返回栈 beginTransaction.addToBackStack(null); //提交事务 beginTransaction.commit(); }这里我们在事务提交之前调用了addToBackStack方法,他可以接收一个名字用于描述返回栈的状态,一般传入null即可。现在重新运行程序,并点击按钮两次,会添加RightFragment和AnotherRightFragment两个到容器中,然后按下返回键,这个时候并没有退出Activity,而是回到了RightFragment。继续按下返回键,RightFragment界面也会消失,容器为空。再次按下返回键,页面才会退出。
这是一个点击事件:
boolean flag = false; public void interactionActivityTest(View view) { if (flag) { AnotherRightFragment anotherRightFragment = new AnotherRightFragment(); Bundle bundle = new Bundle(); long now = System.currentTimeMillis(); Log.d("zhangyu20201012", "interactionActivityTest start AnotherRightFragment now:" + now); bundle.putString("testKey", "" + now); anotherRightFragment.setArguments(bundle); replaceFragment(anotherRightFragment); } else { RightFragment rightFragment = new RightFragment(); Bundle bundle = new Bundle(); long now = System.currentTimeMillis(); Log.d("zhangyu20201012", "interactionActivityTest start RightFragment now:" + now); bundle.putString("testKey", "" + now); rightFragment.setArguments(bundle); replaceFragment(rightFragment); } flag = !flag; }新建一个新的BaseFragment类,在关键的生命周期方法内打印生命周期的信息:
public class BaseFragment extends Fragment { String getTAG() { return "zhangyu1027-" + this.getClass().getSimpleName(); } @Override public void onAttach(@NonNull Context context) { super.onAttach(context); Log.d(getTAG(), "onAttach " + this.hashCode()); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(getTAG(), "onCreate " + this.hashCode()); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Log.d(getTAG(), "onCreateView " + this.hashCode()); return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.d(getTAG(), "onActivityCreated " + this.hashCode()); } @Override public void onStart() { super.onStart(); Log.d(getTAG(), "onStart " + this.hashCode()); } @Override public void onResume() { super.onResume(); Log.d(getTAG(), "onResume " + this.hashCode()); } @Override public void onPause() { super.onPause(); Log.d(getTAG(), "onPause " + this.hashCode()); } @Override public void onStop() { super.onStop(); Log.d(getTAG(), "onStop " + this.hashCode()); } @Override public void onDestroyView() { super.onDestroyView(); Log.d(getTAG(), "onDestroyView " + this.hashCode()); } @Override public void onDestroy() { super.onDestroy(); Log.d(getTAG(), "onDestroy " + this.hashCode()); } @Override public void onDetach() { super.onDetach(); Log.d(getTAG(), "onDetach " + this.hashCode()); } }生命周期为:【onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume 】 点击返回键:
2020-10-27 08:07:17.130 15760-15760/com.example.fragmentdemo D/zhangyu1027-RightFragment: onPause 44450868 2020-10-27 08:07:17.130 15760-15760/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onPause 227039740 2020-10-27 08:07:17.784 15760-15760/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStop 44450868 2020-10-27 08:07:17.784 15760-15760/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onStop 227039740 2020-10-27 08:07:17.786 15760-15760/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroyView 44450868 2020-10-27 08:07:17.787 15760-15760/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroy 44450868 2020-10-27 08:07:17.787 15760-15760/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDetach 44450868 2020-10-27 08:07:17.787 15760-15760/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroyView 227039740 2020-10-27 08:07:17.788 15760-15760/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroy 227039740 2020-10-27 08:07:17.788 15760-15760/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDetach 227039740点击返回键,页面全部一下退出,通过add添加的两个Fragment都直接全部退出。生命周期为: 【onPause -> onStop -> onDestroyView-> onDestroy -> onDetach】,两个Fragment生命周期之间存在交叉。
先添加两个Fragment,生命周期如下: 生命周期为:【onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume 】
2020-10-27 08:09:48.911 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onAttach 245832902 2020-10-27 08:09:48.911 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onCreate 245832902 2020-10-27 08:09:48.914 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onCreateView 245832902 2020-10-27 08:09:48.923 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onActivityCreated 245832902 2020-10-27 08:09:48.923 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStart 245832902 2020-10-27 08:09:48.924 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onResume 245832902 2020-10-27 08:09:50.965 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onAttach 22956878 2020-10-27 08:09:50.965 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onCreate 22956878 2020-10-27 08:09:50.965 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onCreateView 22956878 2020-10-27 08:09:50.977 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onActivityCreated 22956878 2020-10-27 08:09:50.977 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onStart 22956878 2020-10-27 08:09:50.978 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onResume 22956878这个时候点击返回键,会先回到上一个Fragment,再点击一次放回键才会退出页面。 生命周期为:【onPause -> onStop -> onDestroyView-> onDestroy -> onDetach】,两个Fragment生命周期没有交叉。
2020-10-27 08:09:52.413 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onPause 22956878 2020-10-27 08:09:52.414 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onStop 22956878 2020-10-27 08:09:52.414 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroyView 22956878 2020-10-27 08:09:52.419 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroy 22956878 2020-10-27 08:09:52.419 15977-15977/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDetach 22956878 2020-10-27 08:09:56.423 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onPause 245832902 2020-10-27 08:09:56.423 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStop 245832902 2020-10-27 08:09:56.423 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroyView 245832902 2020-10-27 08:09:56.424 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroy 245832902 2020-10-27 08:09:56.425 15977-15977/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDetach 245832902先添加RightFragment,生命周期跟之前一样:【onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume 】 当时呢,当我们添加AnotherRightFragment的时候,AnotherRightFragment的生命周期为先是【onAttach -》onCreate 】,接着RightFragment直接走销毁的生命周期:【onPause -> onStop -> onDestroyView-> onDestroy -> onDetach】。 然后AnotherRightFragment走【onCreateView -> onActivityCreated -> onStart -> onResume】
2020-10-27 08:17:57.397 16178-16178/com.example.fragmentdemo D/zhangyu1027: LifeCycleActivity onCreate127615966 2020-10-27 08:17:58.924 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onAttach 182829729 2020-10-27 08:17:58.924 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onCreate 182829729 2020-10-27 08:17:58.925 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onCreateView 182829729 2020-10-27 08:17:58.944 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onActivityCreated 182829729 2020-10-27 08:17:58.944 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStart 182829729 2020-10-27 08:17:58.944 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onResume 182829729 2020-10-27 08:18:01.920 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onAttach 86636105 2020-10-27 08:18:01.920 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onCreate 86636105 2020-10-27 08:18:01.921 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onPause 182829729 2020-10-27 08:18:01.921 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStop 182829729 2020-10-27 08:18:01.922 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroyView 182829729 2020-10-27 08:18:01.929 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroy 182829729 2020-10-27 08:18:01.929 16178-16178/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDetach 182829729 2020-10-27 08:18:01.930 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onCreateView 86636105 2020-10-27 08:18:01.939 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onActivityCreated 86636105 2020-10-27 08:18:01.939 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onStart 86636105 2020-10-27 08:18:01.939 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onResume 86636105此时点击返回键,整个页面退出:AnotherRightFragment走销毁的生命周期:【onPause -> onStop -> onDestroyView-> onDestroy -> onDetach】
2020-10-27 08:22:05.931 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onPause 86636105 2020-10-27 08:22:06.555 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onStop 86636105 2020-10-27 08:22:06.556 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroyView 86636105 2020-10-27 08:22:06.557 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroy 86636105 2020-10-27 08:22:06.557 16178-16178/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDetach 86636105 2020-10-27 08:22:06.559 16178-16178/com.example.fragmentdemo D/zhangyu1027: LifeCycleActivity onDestroy127615966添加代码
private void transactionFragment(Fragment fragment) { //获取FragmentManager FragmentManager fragmentManager = getSupportFragmentManager(); //开启一个事务 FragmentTransaction beginTransaction = fragmentManager.beginTransaction(); //向容器添加或者替换Fragment beginTransaction.replace(R.id.activity_life_cycle_fl, fragment); //beginTransaction.add(R.id.activity_life_cycle_fl, fragment); //加入返回栈 beginTransaction.addToBackStack(null); //提交事务 beginTransaction.commit(); }先添加两个Fragment, 添加RightFragment,生命周期为:【onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume 】,没有什么疑问,很好理解。 再添加一个AnotherRightFragment,生命周期先为【onAttach -》onCreate 】,跟上一个一样。 不一样的来了,此时RightFragment的生命周期为【onPause -> onStop -> onDestroyView】,没有走【 onDestroy -> onDetach】,因为添加到了返回栈中,RightFragment没有跟当前的Activity解除关联。 然后AnotherRightFragment剩下的生命周期为:【onCreateView -> onActivityCreated -> onStart -> onResume】,这里跟之前一样。
2020-10-27 08:23:40.140 16400-16400/com.example.fragmentdemo D/zhangyu1027: LifeCycleActivity onCreate127615966 2020-10-27 08:23:41.417 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onAttach 119552776 2020-10-27 08:23:41.417 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onCreate 119552776 2020-10-27 08:23:41.418 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onCreateView 119552776 2020-10-27 08:23:41.429 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onActivityCreated 119552776 2020-10-27 08:23:41.429 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStart 119552776 2020-10-27 08:23:41.429 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onResume 119552776 2020-10-27 08:23:42.088 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onAttach 86636105 2020-10-27 08:23:42.088 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onCreate 86636105 2020-10-27 08:23:42.088 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onPause 119552776 2020-10-27 08:23:42.089 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStop 119552776 2020-10-27 08:23:42.090 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroyView 119552776 2020-10-27 08:23:42.094 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onCreateView 86636105 2020-10-27 08:23:42.104 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onActivityCreated 86636105 2020-10-27 08:23:42.105 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onStart 86636105 2020-10-27 08:23:42.106 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onResume 86636105然后点击返回键: 点击第一次:回到上一个Fragment, 栈顶的AnotherRightFragment会销毁,生命周期为:【onPause -> onStop -> onDestroyView-> onDestroy -> onDetach】 RightFragment会重新在展示出来,生命周期为:【onCreateView -> onActivityCreated -> onStart -> onResume 】
2020-10-27 08:28:29.963 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onPause 86636105 2020-10-27 08:28:29.963 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onStop 86636105 2020-10-27 08:28:29.963 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroyView 86636105 2020-10-27 08:28:29.966 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDestroy 86636105 2020-10-27 08:28:29.966 16400-16400/com.example.fragmentdemo D/zhangyu1027-AnotherRightFragment: onDetach 86636105 2020-10-27 08:28:29.966 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onCreateView 119552776 2020-10-27 08:28:29.974 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onActivityCreated 119552776 2020-10-27 08:28:29.975 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStart 119552776 2020-10-27 08:28:29.975 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onResume 119552776再点击:此时页面退出。 生命周期为:【onPause -> onStop -> onDestroyView-> onDestroy -> onDetach】
2020-10-27 08:28:59.252 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onPause 119552776 2020-10-27 08:28:59.253 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onStop 119552776 2020-10-27 08:28:59.253 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroyView 119552776 2020-10-27 08:28:59.254 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDestroy 119552776 2020-10-27 08:28:59.254 16400-16400/com.example.fragmentdemo D/zhangyu1027-RightFragment: onDetach 119552776hide和show的时候生命周期无变化