Fragment的简单介绍
前言
本文主要对Fragment进行简单的说明,介绍一下其生命周期和使用方法。
定义
Fragment在Android3.0被引入,起初是为了在平板等大屏幕上实现多层次的窗格化显示,但现在也普遍应用在手机屏幕上,简单的说,Fragment就是Activity上展示内容的一部分。这里需要注意以下三点:
(1)Fragment不能脱离Activity单独存在,他一定是依附于Activity进行内容的展示。
(2)Fragment有自己的生命周期来接收自己的事件,并通过生命周期方法来与Activity进行交互实现Fragment的添加和删除。
(3)Frgament的生命周期依附于Activity的生命周期,比如说当Activity执行了onPause()方法后依附于该Activity的Fragment也一定执行了onPause()方法。
生命周期
Fragment的生命周期如下:
08-15 11:10:55.863 24142-24142/? E/TestFragment: onAttach
08-15 11:10:55.864 24142-24142/? E/TestFragment: onCreate
08-15 11:10:55.864 24142-24142/? E/TestFragment: onCreateView
08-15 11:10:55.871 24142-24142/? E/TestFragment: onActivityCreated
08-15 11:10:55.871 24142-24142/? E/TestFragment: onStart
08-15 11:10:55.872 24142-24142/? E/TestFragment: onResume
08-15 11:11:06.856 24142-24142/com.zhqy.fragmentdemo E/TestFragment: onPause
08-15 11:11:07.276 24142-24142/com.zhqy.fragmentdemo E/TestFragment: onStop
08-15 11:11:07.276 24142-24142/com.zhqy.fragmentdemo E/TestFragment: onDestroyView
08-15 11:11:07.276 24142-24142/com.zhqy.fragmentdemo E/TestFragment: onDestroy
08-15 11:11:07.276 24142-24142/com.zhqy.fragmentdemo E/TestFragment: onDetach
这是打开一个包含Fragment的Activity又正常关闭Activity后Fragment所调用的生命周期。现在简要说明一下各个生命周期方法:
onAttach:当Fragment与Activity建立起联系时会调用该方法。
onCreate:该Fragment正在创建时会调用此方法。
onCreateView:当Fragment加载布局时会调用此方法。
onActivityCreated:当Activity调用完onCreate方法后调用此方法,通知fragmentActivity创建完毕。
onStart;当前Fragment处于后台且无法与用户进行交互,完全不可见调用此方法。
onResume:当前Fragment位于前台且可以与用户进行交互,完全可见调用此方法。
onPause:当前Fragment处于前台但不可见或者部分可见(例:弹出dialog),无法与用户进行交互调用此方法
onStop:当前Fragment位于后台且无法与用户进行交互,完全不可见调用此方法
onDestoryView:移除该Fragment的布局时调用此方法。
onDestory:即将销毁该Fragment时调用此方法。
onDetach:移除与Activity建立的联系。
说了这么多方法调用,那么它与Activity之间的生命周期方法的调用顺序又是怎么样的呢?现在做一下测试,代码如下:
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("MainActivity","onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
Log.e("MainActivity","onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.e("MainActivity","onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.e("MainActivity","onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.e("MainActivity","onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("MainActivity","onDestroy");
}
}
TestFragment
package com.zhqy.fragmentdemo;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by jackal on 2019/8/15.
*/
public class TestFragment extends Fragment {
@Override
public void onAttach(Context context) {
Log.e("TestFragment","onAttach");
super.onAttach(context);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("TestFragment","onCreate");
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.e("TestFragment","onCreateView");
View view = inflater.inflate(R.layout.fragment_test, container, false);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
Log.e("TestFragment","onActivityCreated");
super.onActivityCreated(savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
Log.e("TestFragment","onStart");
}
@Override
public void onResume() {
super.onResume();
Log.e("TestFragment","onResume");
}
@Override
public void onPause() {
super.onPause();
Log.e("TestFragment","onPause");
}
@Override
public void onStop() {
super.onStop();
Log.e("TestFragment","onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.e("TestFragment","onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("TestFragment","onDestroy");
}
@Override
public void onDetach() {
super.onDetach();
Log.e("TestFragment","onDetach");
}
}
打开该Activity后关闭该Activity,Activity和Fragment的生命周期调用顺序如下:
08-15 11:38:52.226 4896-4896/? E/MainActivity: onCreate
08-15 11:38:52.325 4896-4896/? E/TestFragment: onAttach
08-15 11:38:52.325 4896-4896/? E/TestFragment: onCreate
08-15 11:38:52.326 4896-4896/? E/TestFragment: onCreateView
08-15 11:38:52.334 4896-4896/? E/MainActivity: onStart
08-15 11:38:52.334 4896-4896/? E/TestFragment: onActivityCreated
08-15 11:38:52.335 4896-4896/? E/TestFragment: onStart
08-15 11:38:52.335 4896-4896/? E/MainActivity: onResume
08-15 11:38:52.336 4896-4896/? E/TestFragment: onResume
08-15 11:39:03.129 4896-4896/com.zhqy.fragmentdemo E/MainActivity: onPause
08-15 11:39:03.131 4896-4896/com.zhqy.fragmentdemo E/TestFragment: onPause
08-15 11:39:03.488 4896-4896/com.zhqy.fragmentdemo E/MainActivity: onStop
08-15 11:39:03.488 4896-4896/com.zhqy.fragmentdemo E/TestFragment: onStop
08-15 11:39:03.488 4896-4896/com.zhqy.fragmentdemo E/MainActivity: onDestroy
08-15 11:39:03.489 4896-4896/com.zhqy.fragmentdemo E/TestFragment: onDestroyView
08-15 11:39:03.489 4896-4896/com.zhqy.fragmentdemo E/TestFragment: onDestroy
08-15 11:39:03.489 4896-4896/com.zhqy.fragmentdemo E/TestFragment: onDetach
现在简要说明一下生命周期的执行顺序:
当打开该Activity时会调用onCreate方法,在onCreate方法中又调用了setContentView方法来创建布局,在该布局中包含TestFragment,首先调用onAttach方法建立起Activity与Fragment的联系,然后调用onCreate和onCreateView方法来创建Fragment和添加布局。当Activity调用完onCreate方法后会调用onActivityCreated方法来通知Fragment,此后Fragmengt的生命周期的执行完全取决于Activity,当Activity执行onStart方法,Fragment也执行onStart方法。当Activity执行到onDestory方法即该Activity即将被销毁时,Fragment对先调用onDestoryView来移除布局,再调用onDestory来做销毁Fragment的相关工作,最后执行onDetach方法移除Activity与Fragment的联系。通过对生命方法执行顺序的分析,可以得出这个结论:Fragment先关生命周期方法的执行依附于Activity先关生命周期方法。
应用场景下的生命周期调用
屏幕灭掉
onPause() onSaveInstanceState() onStop()
屏幕解锁
onStart() onResume()
切换到其他Fragment
onPause() onStop() onDestroyView()
切换回本身的Fragment
onCreateView() onActivityCreated() onStart() onResume()
回到桌面
onPause() onSaveInstanceState() onStop()
回到应用
onStart() onResume()
退出应用
onPause() onStop() onDestroyView() onDestroy() onDetach()
Activity生命周期与Fragmengt生命周期的对比
因为Fragment依附于Activity进行内容的展示,所以Fragmengt除了拥有Activity所拥有的的生命周期外,还会在Activity创建和销毁的时候执行响应的生命周期方法来进行Fragment与Activity联系的建立与移除,在切换Activity时销毁Fragment布局等相关生命周期方法。
生命周期对比图.jpg
Fragmeng的使用方法
布局文件中添加
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context="com.zhqy.fragmentdemo.MainActivity">
<fragment
android:id="@+id/testfragment"
android:name="com.zhqy.fragmentdemo.TestFragment"
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_height="match_parent">
</fragment>
<fragment
android:id="@+id/demofragment"
android:name="com.zhqy.fragmentdemo.DemoFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintRight_toRightOf="parent"
></fragment>
</android.support.constraint.ConstraintLayout>
fragment_test.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestFragment"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</android.support.constraint.ConstraintLayout>
fragment_demo.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DemoFragment"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</android.support.constraint.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("MainActivity","onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
Log.e("MainActivity","onStart");
super.onStart();
}
@Override
protected void onResume() {
Log.e("MainActivity","onResume");
super.onResume();
}
@Override
protected void onPause() {
Log.e("MainActivity","onPause");
super.onPause();
}
@Override
protected void onStop() {
Log.e("MainActivity","onStop");
super.onStop();
}
@Override
protected void onDestroy() {
Log.e("MainActivity","onDestroy");
super.onDestroy();
}
}
TestFragment.java
public class TestFragment extends Fragment {
@Override
public void onAttach(Context context) {
Log.e("TestFragment","onAttach");
super.onAttach(context);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
Log.e("TestFragment","onCreate");
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.e("TestFragment","onCreateView");
View view = inflater.inflate(R.layout.fragment_test, container, false);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
Log.e("TestFragment","onActivityCreated");
super.onActivityCreated(savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
Log.e("TestFragment","onStart");
}
@Override
public void onResume() {
Log.e("TestFragment","onResume");
super.onResume();
}
@Override
public void onPause() {
super.onPause();
Log.e("TestFragment","onPause");
}
@Override
public void onStop() {
Log.e("TestFragment","onStop");
super.onStop();
}
@Override
public void onDestroyView() {
Log.e("TestFragment","onDestroyView");
super.onDestroyView();
}
@Override
public void onDestroy() {
Log.e("TestFragment","onDestroy");
super.onDestroy();
}
@Override
public void onDetach() {
Log.e("TestFragment","onDetach");
super.onDetach();
}
}
DemoFragment
public class DemoFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_demo, container, false);
return view;
}
}
测试结果如下:
测试结果.png
代码添加
在Activity的布局文件定义1占位符(FrameLayout)这样做的好处是:可动态Activity中添加不同的 Fragment,更加灵活。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context="com.zhqy.fragmentdemo.MainActivity">
<FrameLayout
android:id="@+id/testfragment"
android:name="com.zhqy.fragmentdemo.TestFragment"
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_height="match_parent">
</FrameLayout>
<FrameLayout
android:id="@+id/demofragment"
android:name="com.zhqy.fragmentdemo.DemoFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintRight_toRightOf="parent"
></FrameLayout>
</android.support.constraint.ConstraintLayout>
MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("MainActivity","onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取FragmentManager
FragmentManager manager=getSupportFragmentManager();
//开启事物
FragmentTransaction fragmentTransaction = manager.beginTransaction();
//将Fragment填充到Activity的对应布局中
fragmentTransaction.replace(R.id.testfragment,new TestFragment());
fragmentTransaction.replace(R.id.demofragment,new TestFragment());
//提交事物
fragmentTransaction.commit();
}
}
测试结果与方法一一致。